517 prev next chunks index CyanogenMod/android_packages_apps_Trebuchet_d223b88f0dbff7cd66876e691345df5c1ede242b_src/com/android/launcher3/LauncherModel.java {strict: [[b], [b], [b], [b], [b], [b], [b], [b], [b]], subset: [[b], [b], [b], [b], [b], [b], [b], [b], [b]]}
line based (standard git) jfstmerge spork
   1 /*                                                                                                       
   2  * Copyright (C) 2008 The Android Open Source Project                                                    
   3  *                                                                                                       
   4  * Licensed under the Apache License, Version 2.0 (the "License");                                       
   5  * you may not use this file except in compliance with the License.                                      
   6  * You may obtain a copy of the License at                                                               
   7  *                                                                                                       
   8  *      http://www.apache.org/licenses/LICENSE-2.0                                                       
   9  *                                                                                                       
  10  * Unless required by applicable law or agreed to in writing, software                                   
  11  * distributed under the License is distributed on an "AS IS" BASIS,                                     
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                              
  13  * See the License for the specific language governing permissions and                                   
  14  * limitations under the License.                                                                        
  15  */                                                                                                      
  16                                                                                                          
  17 package com.android.launcher3;                                                                           
  18                                                                                                          
  19 import android.app.SearchManager;                                                                        
  20 import android.appwidget.AppWidgetManager;                                                               
  21 import android.appwidget.AppWidgetProviderInfo;                                                          
  22 import android.content.BroadcastReceiver;                                                                
  23 import android.content.ComponentName;                                                                    
  24 import android.content.ContentProviderClient;                                                            
  25 import android.content.ContentProviderOperation;                                                         
  26 import android.content.ContentResolver;                                                                  
  27 import android.content.ContentValues;                                                                    
  28 import android.content.Context;                                                                          
  29 import android.content.Intent;                                                                           
  30 import android.content.Intent.ShortcutIconResource;                                                      
  31 import android.content.IntentFilter;                                                                     
  32 import android.content.SharedPreferences;                                                                
  33 import android.content.pm.PackageManager;                                                                
  34 import android.content.pm.ProviderInfo;                                                                  
  35 import android.content.pm.ResolveInfo;                                                                   
  36 import android.content.res.Configuration;                                                                
  37 import android.content.res.Resources;                                                                    
  38 import android.database.Cursor;                                                                          
  39 import android.graphics.Bitmap;                                                                          
  40 import android.graphics.BitmapFactory;                                                                   
  41 import android.net.Uri;                                                                                  
  42 import android.os.Environment;                                                                           
  43 import android.os.Handler;                                                                               
  44 import android.os.HandlerThread;                                                                         
  45 import android.os.Parcelable;                                                                            
  46 import android.os.Process;                                                                               
  47 import android.os.RemoteException;                                                                       
  48 import android.os.SystemClock;                                                                           
  49 import android.provider.BaseColumns;                                                                     
  50 import android.text.TextUtils;                                                                           
  51 import android.util.Log;                                                                                 
  52 import android.util.Pair;                                                                                
  53                                                                                                          
  54 import com.android.launcher3.compat.AppWidgetManagerCompat;                                              
  55 import com.android.launcher3.compat.LauncherActivityInfoCompat;                                          
  56 import com.android.launcher3.compat.LauncherAppsCompat;                                                  
  57 import com.android.launcher3.compat.PackageInstallerCompat;                                              
  58 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;                           
  59 import com.android.launcher3.compat.UserHandleCompat;                                                    
  60 import com.android.launcher3.compat.UserManagerCompat;                                                   
  61                                                                                                          
  62 import java.lang.ref.WeakReference;                                                                      
  63 import java.net.URISyntaxException;                                                                      
  64 import java.security.InvalidParameterException;                                                          
  65 import java.text.Collator;                                                                               
  66 import java.util.ArrayList;                                                                              
  67 import java.util.Arrays;                                                                                 
  68 import java.util.Collection;                                                                             
  69 import java.util.Collections;                                                                            
  70 import java.util.Comparator;                                                                             
  71 import java.util.HashMap;                                                                                
  72 import java.util.HashSet;                                                                                
  73 import java.util.Iterator;                                                                               
  74 import java.util.List;                                                                                   
  75 import java.util.Map.Entry;                                                                              
  76 import java.util.Set;                                                                                    
  77 import java.util.TreeMap;                                                                                
  78 import java.util.concurrent.atomic.AtomicBoolean;                                                        
  79                                                                                                          
  80 /**                                                                                                      
  81  * Maintains in-memory state of the Launcher. It is expected that there should be only one               
  82  * LauncherModel object held in a static. Also provide APIs for updating the database state              
  83  * for the Launcher.                                                                                     
  84  */                                                                                                      
  85 public class LauncherModel extends BroadcastReceiver                                                     
  86         implements LauncherAppsCompat.OnAppsChangedCallbackCompat {                                      
  87     static final boolean DEBUG_LOADERS = false;                                                          
  88     private static final boolean DEBUG_RECEIVER = false;                                                 
  89     private static final boolean REMOVE_UNRESTORED_ICONS = true;                                         
  90                                                                                                          
  91     static final String TAG = "Launcher.Model";                                                          
  92                                                                                                          
  93     // true = use a "More Apps" folder for non-workspace apps on upgrade                                 
  94     // false = strew non-workspace apps across the workspace on upgrade                                  
  95     public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;                                    
  96     public static final int LOADER_FLAG_NONE = 0;                                                        
  97     public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;                                        
  98     public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;                                      
  99                                                                                                          
 100     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons                      
 101     private static final long INVALID_SCREEN_ID = -1L;                                                   
 102                                                                                                          
 103     private final boolean mAppsCanBeOnRemoveableStorage;                                                 
 104     private final boolean mOldContentProviderExists;                                                     
 105                                                                                                          
 106     private final LauncherAppState mApp;                                                                 
 107     private final Object mLock = new Object();                                                           
 108     private DeferredHandler mHandler = new DeferredHandler();                                            
 109     private LoaderTask mLoaderTask;                                                                      
 110     private boolean mIsLoaderTaskRunning;                                                                
 111     private volatile boolean mFlushingWorkerThread;                                                      
 112                                                                                                          
 113     // Specific runnable types that are run on the main thread deferred handler, this allows us to       
 114     // clear all queued binding runnables when the Launcher activity is destroyed.                       
 115     private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;                                            
 116     private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;                                           
 117                                                                                                          
 118     private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";                    
 119                                                                                                          
 120     private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");             
 121     static {                                                                                             
 122         sWorkerThread.start();                                                                           
 123     }                                                                                                    
 124     private static final Handler sWorker = new Handler(sWorkerThread.getLooper());                       
 125                                                                                                          
 126     // We start off with everything not loaded.  After that, we assume that                              
 127     // our monitoring of the package manager provides all updates and we never                           
 128     // need to do a requery.  These are only ever touched from the loader thread.                        
 129     private boolean mWorkspaceLoaded;                                                                    
 130     private boolean mAllAppsLoaded;                                                                      
 131                                                                                                          
 132     // When we are loading pages synchronously, we can't just post the binding of items on the side      
 133     // pages as this delays the rotation process.  Instead, we wait for a callback from the first        
 134     // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start       
 135     // a normal load, we also clear this set of Runnables.                                               
 136     static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();                 
 137                                                                                                          
 138     private WeakReference<Callbacks> mCallbacks;                                                         
 139                                                                                                          
 140     // < only access in worker thread >                                                                  
 141     AllAppsList mBgAllAppsList;                                                                          
 142                                                                                                          
 143     // The lock that must be acquired before referencing any static bg data structures.  Unlike          
 144     // other locks, this one can generally be held long-term because we never expect any of these        
 145     // static data structures to be referenced outside of the worker thread except on the first          
 146     // load after configuration change.                                                                  
 147     static final Object sBgLock = new Object();                                                          
 148                                                                                                          
 149     // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by               
 150     // LauncherModel to their ids                                                                        
 151     static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();                  
 152                                                                                                          
 153     // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts       
 154     //       created by LauncherModel that are directly on the home screen (however, no widgets or       
 155     //       shortcuts within folders).                                                                  
 156     static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();                      
 157                                                                                                          
 158     // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()    
 159     static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =                                        
 160         new ArrayList<LauncherAppWidgetInfo>();                                                          
 161                                                                                                          
 162     // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()                   
 163     static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();                 
 164                                                                                                          
 165     // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database      
 166     static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();                 
 167                                                                                                          
 168     // sBgWorkspaceScreens is the ordered set of workspace screens.                                      
 169     static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();                            
 170                                                                                                          
 171     // sPendingPackages is a set of packages which could be on sdcard and are not available yet          
 172     static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =                           
 173             new HashMap<UserHandleCompat, HashSet<String>>();                                            
 174                                                                                                          
 175     // </ only access in worker thread >                                                                 
 176                                                                                                          
 177     private IconCache mIconCache;                                                                        
 178                                                                                                          
 179     protected int mPreviousConfigMcc;                                                                    
 180                                                                                                          
 181     private final LauncherAppsCompat mLauncherApps;                                                      
 182     private final UserManagerCompat mUserManager;                                                        
 183                                                                                                          
 184     public interface Callbacks {                                                                         
 185         public boolean setLoadOnResume();                                                                
 186         public int getCurrentWorkspaceScreen();                                                          
 187         public void startBinding();                                                                      
 188         public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,                         
 189                               boolean forceAnimateIcons);                                                
 190         public void bindScreens(ArrayList<Long> orderedScreenIds);                                       
 191         public void bindAddScreens(ArrayList<Long> orderedScreenIds);                                    
 192         public void bindFolders(HashMap<Long,FolderInfo> folders);                                       
 193         public void finishBindingItems(boolean upgradePath);                                             
 194         public void bindAppWidget(LauncherAppWidgetInfo info);                                           
 195         public void bindAllApplications(ArrayList<AppInfo> apps);                                        
 196         public void bindAppsAdded(ArrayList<Long> newScreens,                                            
 197                                   ArrayList<ItemInfo> addNotAnimated,                                    
 198                                   ArrayList<ItemInfo> addAnimated,                                       
 199                                   ArrayList<AppInfo> addedApps);                                         
 200         public void bindAppsUpdated(ArrayList<AppInfo> apps);                                            
 201         public void bindAppsRestored(ArrayList<AppInfo> apps);                                           
 202         public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);                       
 203         public void updatePackageBadge(String packageName);                                              
 204         public void bindComponentsRemoved(ArrayList<String> packageNames,                                
 205                         ArrayList<AppInfo> appInfos, UserHandleCompat user);                             
 206         public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);                          
 207         public void bindSearchablesChanged();                                                            
 208         public boolean isAllAppsButtonRank(int rank);                                                    
 209         public void onPageBoundSynchronously(int page);                                                  
 210         public void dumpLogsToLocalData();                                                               
 211     }                                                                                                    
 212                                                                                                          
 213     public interface ItemInfoFilter {                                                                    
 214         public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);                     
 215     }                                                                                                    
 216                                                                                                          
 217     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {                      
 218         Context context = app.getContext();                                                              
 219                                                                                                          
 220         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();                        
 221         String oldProvider = context.getString(R.string.old_launcher_provider_uri);                      
 222         // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different               
 223         // resource string.                                                                              
 224         String redirectAuthority = Uri.parse(oldProvider).getAuthority();                                
 225         ProviderInfo providerInfo =                                                                      
 226                 context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY, 0);                
 227         ProviderInfo redirectProvider =                                                                  
 228                 context.getPackageManager().resolveContentProvider(redirectAuthority, 0);                
 229                                                                                                          
 230         Log.d(TAG, "Old launcher provider: " + oldProvider);                                             
 231         mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);                
 232                                                                                                          
 233         if (mOldContentProviderExists) {                                                                 
 234             Log.d(TAG, "Old launcher provider exists.");                                                 
 235         } else {                                                                                         
 236             Log.d(TAG, "Old launcher provider does not exist.");                                         
 237         }                                                                                                
 238                                                                                                          
 239         mApp = app;                                                                                      
 240         mBgAllAppsList = new AllAppsList(iconCache, appFilter);                                          
 241         mIconCache = iconCache;                                                                          
 242                                                                                                          
 243         final Resources res = context.getResources();                                                    
 244         Configuration config = res.getConfiguration();                                                   
 245         mPreviousConfigMcc = config.mcc;                                                                 
 246         mLauncherApps = LauncherAppsCompat.getInstance(context);                                         
 247         mUserManager = UserManagerCompat.getInstance(context);                                           
 248     }                                                                                                    
 249                                                                                                          
 250     /** Runs the specified runnable immediately if called from the main thread, otherwise it is          
 251      * posted on the main thread handler. */                                                             
 252     private void runOnMainThread(Runnable r) {                                                           
 253         runOnMainThread(r, 0);                                                                           
 254     }                                                                                                    
 255     private void runOnMainThread(Runnable r, int type) {                                                 
 256         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 257             // If we are on the worker thread, post onto the main handler                                
 258             mHandler.post(r);                                                                            
 259         } else {                                                                                         
 260             r.run();                                                                                     
 261         }                                                                                                
 262     }                                                                                                    
 263                                                                                                          
 264     /** Runs the specified runnable immediately if called from the worker thread, otherwise it is        
 265      * posted on the worker thread handler. */                                                           
 266     private static void runOnWorkerThread(Runnable r) {                                                  
 267         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 268             r.run();                                                                                     
 269         } else {                                                                                         
 270             // If we are not on the worker thread, then post to the worker handler                       
 271             sWorker.post(r);                                                                             
 272         }                                                                                                
 273     }                                                                                                    
 274                                                                                                          
 275     boolean canMigrateFromOldLauncherDb(Launcher launcher) {                                             
 276         return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;                         
 277     }                                                                                                    
 278                                                                                                          
 279     static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,               
 280                                  long screen) {                                                          
 281         LauncherAppState app = LauncherAppState.getInstance();                                           
 282         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                    
 283         final int xCount = (int) grid.numColumns;                                                        
 284         final int yCount = (int) grid.numRows;                                                           
 285         boolean[][] occupied = new boolean[xCount][yCount];                                              
 286                                                                                                          
 287         int cellX, cellY, spanX, spanY;                                                                  
 288         for (int i = 0; i < items.size(); ++i) {                                                         
 289             final ItemInfo item = items.get(i);                                                          
 290             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                        
 291                 if (item.screenId == screen) {                                                           
 292                     cellX = item.cellX;                                                                  
 293                     cellY = item.cellY;                                                                  
 294                     spanX = item.spanX;                                                                  
 295                     spanY = item.spanY;                                                                  
 296                     for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) {                
 297                         for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) {            
 298                             occupied[x][y] = true;                                                       
 299                         }                                                                                
 300                     }                                                                                    
 301                 }                                                                                        
 302             }                                                                                            
 303         }                                                                                                
 304                                                                                                          
 305         return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);                            
 306     }                                                                                                    
 307     static Pair<Long, int[]> findNextAvailableIconSpace(Context context, String name,                    
 308                                                         Intent launchIntent,                             
 309                                                         int firstScreenIndex,                            
 310                                                         ArrayList<Long> workspaceScreens) {              
 311         // Lock on the app so that we don't try and get the items while apps are being added             
 312         LauncherAppState app = LauncherAppState.getInstance();                                           
 313         LauncherModel model = app.getModel();                                                            
 314         boolean found = false;                                                                           
 315         synchronized (app) {                                                                             
 316             if (sWorkerThread.getThreadId() != Process.myTid()) {                                        
 317                 // Flush the LauncherModel worker thread, so that if we just did another                 
 318                 // processInstallShortcut, we give it time for its shortcut to get added to the          
 319                 // database (getItemsInLocalCoordinates reads the database)                              
 320                 model.flushWorkerThread();                                                               
 321             }                                                                                            
 322             final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);         
 323                                                                                                          
 324             // Try adding to the workspace screens incrementally, starting at the default or center      
 325             // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))       
 326             firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size());                      
 327             int count = workspaceScreens.size();                                                         
 328             for (int screen = firstScreenIndex; screen < count && !found; screen++) {                    
 329                 int[] tmpCoordinates = new int[2];                                                       
 330                 if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates,                            
 331                         workspaceScreens.get(screen))) {                                                 
 332                     // Update the Launcher db                                                            
 333                     return new Pair<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);          
 334                 }                                                                                        
 335             }                                                                                            
 336         }                                                                                                
 337         return null;                                                                                     
 338     }                                                                                                    
 339                                                                                                          
 340 <<<<<<< GitAnalyzerPlus_ours                                                                             
 341     public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {                       
 342         // Process the updated package state                                                             
 343         Runnable r = new Runnable() {                                                                    
 344             public void run() {                                                                          
 345                 Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                      
 346                 if (callbacks != null) {                                                                 
 347                     callbacks.updatePackageState(installInfo);                                           
 348                 }                                                                                        
 349             }                                                                                            
 350         };                                                                                               
 351         mHandler.post(r);                                                                                
 352     }                                                                                                    
 353                                                                                                          
 354     public void updatePackageBadge(final String packageName) {                                           
 355         // Process the updated package badge                                                             
 356         Runnable r = new Runnable() {                                                                    
 357             public void run() {                                                                          
 358                 Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                      
 359                 if (callbacks != null) {                                                                 
 360                     callbacks.updatePackageBadge(packageName);                                           
 361                 }                                                                                        
 362             }                                                                                            
 363         };                                                                                               
 364         mHandler.post(r);                                                                                
 365     }                                                                                                    
 366                                                                                                          
 367     public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {              
 368         final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                        
 369                                                                                                          
 370         if (allAppsApps == null) {                                                                       
 371             throw new RuntimeException("allAppsApps must not be null");                                  
 372         }                                                                                                
 373         if (allAppsApps.isEmpty()) {                                                                     
 374             return;                                                                                      
 375         }                                                                                                
 376                                                                                                          
 377         final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                           
 378         Iterator<AppInfo> iter = allAppsApps.iterator();                                                 
 379         while (iter.hasNext()) {                                                                         
 380             ItemInfo a = iter.next();                                                                    
 381             if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {                               
 382                 restoredAppsFinal.add((AppInfo) a);                                                      
 383             }                                                                                            
 384         }                                                                                                
 385                                                                                                          
 386         // Process the newly added applications and add them to the database first                       
 387         Runnable r = new Runnable() {                                                                    
 388             public void run() {                                                                          
 389                 runOnMainThread(new Runnable() {                                                         
 390                     public void run() {                                                                  
 391                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
 392                         if (callbacks == cb && cb != null) {                                             
 393                             if (!restoredAppsFinal.isEmpty()) {                                          
 394                                 for (AppInfo info : restoredAppsFinal) {                                 
 395                                     final Intent intent = info.getIntent();                              
 396                                     if (intent != null) {                                                
 397                                         mIconCache.deletePreloadedIcon(intent.getComponent(),            
 398                                                 info.user);                                              
 399                                     }                                                                    
 400                                 }                                                                        
 401                                 callbacks.bindAppsUpdated(restoredAppsFinal);                            
 402                             }                                                                            
 403                             callbacks.bindAppsAdded(null, null, null, allAppsApps);                      
 404                         }                                                                                
 405                     }                                                                                    
 406                 });                                                                                      
 407             }                                                                                            
 408         };                                                                                               
 409         runOnWorkerThread(r);                                                                            
 410 ||||||| GitAnalyzerPlus_base                                                                             
 411 <<<<<<< OURS                                                                                             
 412     public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,      
 413                                     final ArrayList<AppInfo> allAppsApps) {                              
 414         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                     
 415         addAndBindAddedApps(context, workspaceApps, cb, allAppsApps);                                    
 416 =======                                                                                                  
 417     public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {              
 418         final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                        
 419                                                                                                          
 420         if (allAppsApps == null) {                                                                       
 421             throw new RuntimeException("allAppsApps must not be null");                                  
 422         }                                                                                                
 423         if (allAppsApps.isEmpty()) {                                                                     
 424             return;                                                                                      
 425         }                                                                                                
 426                                                                                                          
 427         final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                           
 428         Iterator<AppInfo> iter = allAppsApps.iterator();                                                 
 429         while (iter.hasNext()) {                                                                         
 430             ItemInfo a = iter.next();                                                                    
 431             if (LauncherModel.appWasRestored(ctx, a.getIntent())) {                                      
 432                 restoredAppsFinal.add((AppInfo) a);                                                      
 433             }                                                                                            
 434         }                                                                                                
 435                                                                                                          
 436         // Process the newly added applications and add them to the database first                       
 437         Runnable r = new Runnable() {                                                                    
 438             public void run() {                                                                          
 439                 runOnMainThread(new Runnable() {                                                         
 440                     public void run() {                                                                  
 441                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
 442                         if (callbacks == cb && cb != null) {                                             
 443                             callbacks.bindAppsAdded(null, null, null, allAppsApps);                      
 444                             if (!restoredAppsFinal.isEmpty()) {                                          
 445                                 callbacks.bindAppsUpdated(restoredAppsFinal);                            
 446                             }                                                                            
 447                         }                                                                                
 448                     }                                                                                    
 449                 });                                                                                      
 450             }                                                                                            
 451         };                                                                                               
 452         runOnWorkerThread(r);                                                                            
 453 >>>>>>> THEIRS                                                                                           
 454     }                                                                                                    
 455     public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,      
 456                                 final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) {       
 457         if (workspaceApps == null || allAppsApps == null) {                                              
 458             throw new RuntimeException("workspaceApps and allAppsApps must not be null");                
 459         }                                                                                                
 460         if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) {                                          
 461             return;                                                                                      
 462         }                                                                                                
 463         // Process the newly added applications and add them to the database first                       
 464         Runnable r = new Runnable() {                                                                    
 465             public void run() {                                                                          
 466                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();               
 467                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                
 468                 final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                   
 469                                                                                                          
 470                 // Get the list of workspace screens.  We need to append to this list and                
 471                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been             
 472                 // called.                                                                               
 473                 ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                
 474                 TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                 
 475                 for (Integer i : orderedScreens.keySet()) {                                              
 476                     long screenId = orderedScreens.get(i);                                               
 477                     workspaceScreens.add(screenId);                                                      
 478                 }                                                                                        
 479                                                                                                          
 480                 synchronized(sBgLock) {                                                                  
 481                     Iterator<ItemInfo> iter = workspaceApps.iterator();                                  
 482                     while (iter.hasNext()) {                                                             
 483                         ItemInfo a = iter.next();                                                        
 484                         final String name = a.title.toString();                                          
 485                         final Intent launchIntent = a.getIntent();                                       
 486                                                                                                          
 487                         // Short-circuit this logic if the icon exists somewhere on the workspace        
 488                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {                 
 489                             // Only InstallShortcutReceiver sends us shortcutInfos, ignore them          
 490                             if (a instanceof AppInfo &&                                                  
 491                                     LauncherModel.appWasRestored(context, launchIntent)) {               
 492                                 restoredAppsFinal.add((AppInfo) a);                                      
 493                             }                                                                            
 494                             continue;                                                                    
 495                         }                                                                                
 496                                                                                                          
 497                         // Add this icon to the db, creating a new page if necessary.  If there          
 498                         // is only the empty page then we just add items to the first page.              
 499                         // Otherwise, we add them to the next pages.                                     
 500                         int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;                   
 501                         Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,     
 502                                 name, launchIntent, startSearchPageIndex, workspaceScreens);             
 503                         if (coords == null) {                                                            
 504                             LauncherProvider lp = LauncherAppState.getLauncherProvider();                
 505                                                                                                          
 506                             // If we can't find a valid position, then just add a new screen.            
 507                             // This takes time so we need to re-queue the add until the new              
 508                             // page is added.  Create as many screens as necessary to satisfy            
 509                             // the startSearchPageIndex.                                                 
 510                             int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -                   
 511                                     workspaceScreens.size());                                            
 512                             while (numPagesToAdd > 0) {                                                  
 513                                 long screenId = lp.generateNewScreenId();                                
 514                                 // Save the screen id for binding in the workspace                       
 515                                 workspaceScreens.add(screenId);                                          
 516                                 addedWorkspaceScreensFinal.add(screenId);                                
 517                                 numPagesToAdd--;                                                         
 518                             }                                                                            
 519                                                                                                          
 520                             // Find the coordinate again                                                 
 521                             coords = LauncherModel.findNextAvailableIconSpace(context,                   
 522                                     name, launchIntent, startSearchPageIndex, workspaceScreens);         
 523                         }                                                                                
 524                         if (coords == null) {                                                            
 525 =======                                                                                                  
 526     public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,      
 527                                     final ArrayList<AppInfo> allAppsApps) {                              
 528         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                     
 529         addAndBindAddedApps(context, workspaceApps, cb, allAppsApps);                                    
 530 >>>>>>> GitAnalyzerPlus_theirs                                                                           
 531     }                                                                                                    
 532                                                                                                          
 533     public void addAndBindAddedWorkspaceApps(final Context context,                                      
 534             final ArrayList<ItemInfo> workspaceApps) {                                                   
 535         final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                        
 536                                                                                                          
 537         if (workspaceApps == null) {                                                                     
 538             throw new RuntimeException("workspaceApps and allAppsApps must not be null");                
 539         }                                                                                                
 540         if (workspaceApps.isEmpty()) {                                                                   
 541             return;                                                                                      
 542         }                                                                                                
 543         // Process the newly added applications and add them to the database first                       
 544         Runnable r = new Runnable() {                                                                    
 545             public void run() {                                                                          
 546                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();               
 547                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                
 548                                                                                                          
 549                 // Get the list of workspace screens.  We need to append to this list and                
 550                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been             
 551                 // called.                                                                               
 552                 ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                
 553                 TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                 
 554                 for (Integer i : orderedScreens.keySet()) {                                              
 555                     long screenId = orderedScreens.get(i);                                               
 556                     workspaceScreens.add(screenId);                                                      
 557                 }                                                                                        
 558                                                                                                          
 559                 synchronized(sBgLock) {                                                                  
 560                     Iterator<ItemInfo> iter = workspaceApps.iterator();                                  
 561                     while (iter.hasNext()) {                                                             
 562                         ItemInfo a = iter.next();                                                        
 563                         final String name = a.title.toString();                                          
 564                         final Intent launchIntent = a.getIntent();                                       
 565                                                                                                          
 566                         // Short-circuit this logic if the icon exists somewhere on the workspace        
 567                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {                 
 568 <<<<<<< GitAnalyzerPlus_ours                                                                             
 569                             // Only InstallShortcutReceiver sends us shortcutInfos, ignore them          
 570                             if (a instanceof AppInfo &&                                                  
 571                                     LauncherModel.appWasPromise(context, launchIntent, a.user)) {        
 572                                 restoredAppsFinal.add((AppInfo) a);                                      
 573                             }                                                                            
 574 ||||||| GitAnalyzerPlus_base                                                                             
 575                 });                                                                                      
 576             }                                                                                            
 577         };                                                                                               
 578         runOnWorkerThread(r);                                                                            
 579 >>>>>>> THEIRS                                                                                           
 580     }                                                                                                    
 581     public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,      
 582                                 final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) {       
 583         if (workspaceApps == null || allAppsApps == null) {                                              
 584             throw new RuntimeException("workspaceApps and allAppsApps must not be null");                
 585         }                                                                                                
 586         if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) {                                          
 587             return;                                                                                      
 588         }                                                                                                
 589         // Process the newly added applications and add them to the database first                       
 590         Runnable r = new Runnable() {                                                                    
 591             public void run() {                                                                          
 592                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();               
 593                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                
 594                 final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                   
 595                                                                                                          
 596                 // Get the list of workspace screens.  We need to append to this list and                
 597                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been             
 598                 // called.                                                                               
 599                 ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                
 600                 TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                 
 601                 for (Integer i : orderedScreens.keySet()) {                                              
 602                     long screenId = orderedScreens.get(i);                                               
 603                     workspaceScreens.add(screenId);                                                      
 604                 }                                                                                        
 605                                                                                                          
 606                 synchronized(sBgLock) {                                                                  
 607                     Iterator<ItemInfo> iter = workspaceApps.iterator();                                  
 608                     while (iter.hasNext()) {                                                             
 609                         ItemInfo a = iter.next();                                                        
 610                         final String name = a.title.toString();                                          
 611                         final Intent launchIntent = a.getIntent();                                       
 612                                                                                                          
 613                         // Short-circuit this logic if the icon exists somewhere on the workspace        
 614                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {                 
 615                             // Only InstallShortcutReceiver sends us shortcutInfos, ignore them          
 616                             if (a instanceof AppInfo &&                                                  
 617                                     LauncherModel.appWasRestored(context, launchIntent)) {               
 618                                 restoredAppsFinal.add((AppInfo) a);                                      
 619                             }                                                                            
 620                             continue;                                                                    
 621                         }                                                                                
 622                                                                                                          
 623                         // Add this icon to the db, creating a new page if necessary.  If there          
 624                         // is only the empty page then we just add items to the first page.              
 625                         // Otherwise, we add them to the next pages.                                     
 626                         int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;                   
 627                         Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,     
 628                                 name, launchIntent, startSearchPageIndex, workspaceScreens);             
 629                         if (coords == null) {                                                            
 630                             LauncherProvider lp = LauncherAppState.getLauncherProvider();                
 631                                                                                                          
 632                             // If we can't find a valid position, then just add a new screen.            
 633                             // This takes time so we need to re-queue the add until the new              
 634                             // page is added.  Create as many screens as necessary to satisfy            
 635                             // the startSearchPageIndex.                                                 
 636                             int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -                   
 637                                     workspaceScreens.size());                                            
 638                             while (numPagesToAdd > 0) {                                                  
 639                                 long screenId = lp.generateNewScreenId();                                
 640                                 // Save the screen id for binding in the workspace                       
 641                                 workspaceScreens.add(screenId);                                          
 642                                 addedWorkspaceScreensFinal.add(screenId);                                
 643                                 numPagesToAdd--;                                                         
 644                             }                                                                            
 645                                                                                                          
 646                             // Find the coordinate again                                                 
 647                             coords = LauncherModel.findNextAvailableIconSpace(context,                   
 648                                     name, launchIntent, startSearchPageIndex, workspaceScreens);         
 649                         }                                                                                
 650                         if (coords == null) {                                                            
 651                             throw new RuntimeException("Coordinates should not be null");                
 652                         }                                                                                
 653                                                                                                          
 654                         ShortcutInfo shortcutInfo;                                                       
 655                         if (a instanceof ShortcutInfo) {                                                 
 656                             shortcutInfo = (ShortcutInfo) a;                                             
 657                         } else if (a instanceof AppInfo) {                                               
 658                             shortcutInfo = ((AppInfo) a).makeShortcut();                                 
 659                         } else {                                                                         
 660                             throw new RuntimeException("Unexpected info type");                          
 661                         }                                                                                
 662                                                                                                          
 663                         // Add the shortcut to the db                                                    
 664                         addItemToDatabase(context, shortcutInfo,                                         
 665                                 LauncherSettings.Favorites.CONTAINER_DESKTOP,                            
 666                                 coords.first, coords.second[0], coords.second[1], false);                
 667                         // Save the ShortcutInfo for binding in the workspace                            
 668                         addedShortcutsFinal.add(shortcutInfo);                                           
 669                     }                                                                                    
 670                 }                                                                                        
 671                                                                                                          
 672                 // Update the workspace screens                                                          
 673                 updateWorkspaceScreenOrder(context, workspaceScreens);                                   
 674                                                                                                          
 675                 if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) {                          
 676                     runOnMainThread(new Runnable() {                                                     
 677                         public void run() {                                                              
 678                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                 
 679                             if (callbacks == cb && cb != null) {                                         
 680                                 final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();       
 681                                 final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();    
 682                                 if (!addedShortcutsFinal.isEmpty()) {                                    
 683                                     ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 🔵
 684                                     long lastScreenId = info.screenId;                                   
 685                                     for (ItemInfo i : addedShortcutsFinal) {                             
 686                                         if (i.screenId == lastScreenId) {                                
 687                                             addAnimated.add(i);                                          
 688                                         } else {                                                         
 689                                             addNotAnimated.add(i);                                       
 690                                         }                                                                
 691                                     }                                                                    
 692                                 }                                                                        
 693                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,                      
 694 =======                                                                                                  
 695 >>>>>>> GitAnalyzerPlus_theirs                                                                           
 696                             continue;                                                                    
 697                         }                                                                                
 698                                                                                                          
 699                         // Add this icon to the db, creating a new page if necessary.  If there          
 700                         // is only the empty page then we just add items to the first page.              
 701                         // Otherwise, we add them to the next pages.                                     
 702                         int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;                   
 703                         Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,     
 704                                 name, launchIntent, startSearchPageIndex, workspaceScreens);             
 705                         if (coords == null) {                                                            
 706                             LauncherProvider lp = LauncherAppState.getLauncherProvider();                
 707                                                                                                          
 708                             // If we can't find a valid position, then just add a new screen.            
 709                             // This takes time so we need to re-queue the add until the new              
 710                             // page is added.  Create as many screens as necessary to satisfy            
 711                             // the startSearchPageIndex.                                                 
 712                             int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -                   
 713                                     workspaceScreens.size());                                            
 714                             while (numPagesToAdd > 0) {                                                  
 715                                 long screenId = lp.generateNewScreenId();                                
 716                                 // Save the screen id for binding in the workspace                       
 717                                 workspaceScreens.add(screenId);                                          
 718                                 addedWorkspaceScreensFinal.add(screenId);                                
 719                                 numPagesToAdd--;                                                         
 720                             }                                                                            
 721                                                                                                          
 722                             // Find the coordinate again                                                 
 723                             coords = LauncherModel.findNextAvailableIconSpace(context,                   
 724                                     name, launchIntent, startSearchPageIndex, workspaceScreens);         
 725                         }                                                                                
 726                         if (coords == null) {                                                            
 727                             throw new RuntimeException("Coordinates should not be null");                
 728                         }                                                                                
 729                                                                                                          
 730                         ShortcutInfo shortcutInfo;                                                       
 731                         if (a instanceof ShortcutInfo) {                                                 
 732                             shortcutInfo = (ShortcutInfo) a;                                             
 733                         } else if (a instanceof AppInfo) {                                               
 734                             shortcutInfo = ((AppInfo) a).makeShortcut();                                 
 735                         } else {                                                                         
 736                             throw new RuntimeException("Unexpected info type");                          
 737                         }                                                                                
 738                                                                                                          
 739                         // Add the shortcut to the db                                                    
 740                         addItemToDatabase(context, shortcutInfo,                                         
 741                                 LauncherSettings.Favorites.CONTAINER_DESKTOP,                            
 742                                 coords.first, coords.second[0], coords.second[1], false);                
 743                         // Save the ShortcutInfo for binding in the workspace                            
 744                         addedShortcutsFinal.add(shortcutInfo);                                           
 745                     }                                                                                    
 746                 }                                                                                        
 747                                                                                                          
 748                 // Update the workspace screens                                                          
 749                 updateWorkspaceScreenOrder(context, workspaceScreens);                                   
 750                                                                                                          
 751                 if (!addedShortcutsFinal.isEmpty()) {                                                    
 752                     runOnMainThread(new Runnable() {                                                     
 753                         public void run() {                                                              
 754                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                 
 755                             if (callbacks == cb && cb != null) {                                         
 756                                 final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();       
 757                                 final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();    
 758                                 if (!addedShortcutsFinal.isEmpty()) {                                    
 759                                     ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 🔵
 760                                     long lastScreenId = info.screenId;                                   
 761                                     for (ItemInfo i : addedShortcutsFinal) {                             
 762                                         if (i.screenId == lastScreenId) {                                
 763                                             addAnimated.add(i);                                          
 764                                         } else {                                                         
 765                                             addNotAnimated.add(i);                                       
 766                                         }                                                                
 767                                     }                                                                    
 768                                 }                                                                        
 769                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,                      
 770 <<<<<<< GitAnalyzerPlus_ours                                                                             
 771                                         addNotAnimated, addAnimated, null);                              
 772                                 if (!restoredAppsFinal.isEmpty()) {                                      
 773                                     callbacks.bindAppsUpdated(restoredAppsFinal);                        
 774                                 }                                                                        
 775 ||||||| GitAnalyzerPlus_base                                                                             
 776                         }                                                                                
 777                         if (coords == null) {                                                            
 778                             throw new RuntimeException("Coordinates should not be null");                
 779                         }                                                                                
 780                                                                                                          
 781                         ShortcutInfo shortcutInfo;                                                       
 782                         if (a instanceof ShortcutInfo) {                                                 
 783                             shortcutInfo = (ShortcutInfo) a;                                             
 784                         } else if (a instanceof AppInfo) {                                               
 785                             shortcutInfo = ((AppInfo) a).makeShortcut();                                 
 786                         } else {                                                                         
 787                             throw new RuntimeException("Unexpected info type");                          
 788                         }                                                                                
 789                                                                                                          
 790                         // Add the shortcut to the db                                                    
 791                         addItemToDatabase(context, shortcutInfo,                                         
 792                                 LauncherSettings.Favorites.CONTAINER_DESKTOP,                            
 793                                 coords.first, coords.second[0], coords.second[1], false);                
 794                         // Save the ShortcutInfo for binding in the workspace                            
 795                         addedShortcutsFinal.add(shortcutInfo);                                           
 796                     }                                                                                    
 797                 }                                                                                        
 798                                                                                                          
 799                 // Update the workspace screens                                                          
 800                 updateWorkspaceScreenOrder(context, workspaceScreens);                                   
 801                                                                                                          
 802                 if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) {                          
 803                     runOnMainThread(new Runnable() {                                                     
 804                         public void run() {                                                              
 805                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                 
 806                             if (callbacks == cb && cb != null) {                                         
 807                                 final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();       
 808                                 final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();    
 809                                 if (!addedShortcutsFinal.isEmpty()) {                                    
 810                                     ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 🔵
 811                                     long lastScreenId = info.screenId;                                   
 812                                     for (ItemInfo i : addedShortcutsFinal) {                             
 813                                         if (i.screenId == lastScreenId) {                                
 814                                             addAnimated.add(i);                                          
 815                                         } else {                                                         
 816                                             addNotAnimated.add(i);                                       
 817                                         }                                                                
 818                                     }                                                                    
 819                                 }                                                                        
 820                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,                      
 821 <<<<<<< OURS                                                                                             
 822                                         addNotAnimated, addAnimated, allAppsApps);                       
 823 =======                                                                                                  
 824                                         addNotAnimated, addAnimated, null);                              
 825                                 if (!restoredAppsFinal.isEmpty()) {                                      
 826                                     callbacks.bindAppsUpdated(restoredAppsFinal);                        
 827                                 }                                                                        
 828 >>>>>>> THEIRS                                                                                           
 829                             }                                                                            
 830                         }                                                                                
 831                     });                                                                                  
 832                 }                                                                                        
 833             }                                                                                            
 834         };                                                                                               
 835         runOnWorkerThread(r);                                                                            
 836     }                                                                                                    
 837                                                                                                          
 838     public Bitmap getFallbackIcon() {                                                                    
 839         if (mDefaultIcon == null) {                                                                      
 840             final Context context = LauncherAppState.getInstance().getContext();                         
 841             mDefaultIcon = Utilities.createIconBitmap(                                                   
 842                     mIconCache.getFullResDefaultActivityIcon(), context);                                
 843         }                                                                                                
 844         return Bitmap.createBitmap(mDefaultIcon);                                                        
 845     }                                                                                                    
 846                                                                                                          
 847     public void unbindItemInfosAndClearQueuedBindRunnables() {                                           
 848         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 849             throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +     
 850                     "main thread");                                                                      
 851         }                                                                                                
 852                                                                                                          
 853         // Clear any deferred bind runnables                                                             
 854         mDeferredBindRunnables.clear();                                                                  
 855         // Remove any queued bind runnables                                                              
 856         mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);                                 
 857         // Unbind all the workspace items                                                                
 858         unbindWorkspaceItemsOnMainThread();                                                              
 859     }                                                                                                    
 860                                                                                                          
 861     /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */                        
 862     void unbindWorkspaceItemsOnMainThread() {                                                            
 863         // Ensure that we don't use the same workspace items data structure on the main thread           
 864         // by making a copy of workspace items first.                                                    
 865         final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();                         
 866         final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();                             
 867         synchronized (sBgLock) {                                                                         
 868             tmpWorkspaceItems.addAll(sBgWorkspaceItems);                                                 
 869             tmpAppWidgets.addAll(sBgAppWidgets);                                                         
 870         }                                                                                                
 871         Runnable r = new Runnable() {                                                                    
 872                 @Override                                                                                
 873                 public void run() {                                                                      
 874                    for (ItemInfo item : tmpWorkspaceItems) {                                             
 875                        item.unbind();                                                                    
 876                    }                                                                                     
 877                    for (ItemInfo item : tmpAppWidgets) {                                                 
 878                        item.unbind();                                                                    
 879                    }                                                                                     
 880                 }                                                                                        
 881             };                                                                                           
 882         runOnMainThread(r);                                                                              
 883     }                                                                                                    
 884                                                                                                          
 885     /**                                                                                                  
 886      * Adds an item to the DB if it was not created previously, or move it to a new                      
 887      * <container, screen, cellX, cellY>                                                                 
 888      */                                                                                                  
 889     static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,                  
 890             long screenId, int cellX, int cellY) {                                                       
 891         if (item.container == ItemInfo.NO_ID) {                                                          
 892             // From all apps                                                                             
 893             addItemToDatabase(context, item, container, screenId, cellX, cellY, false);                  
 894         } else {                                                                                         
 895             // From somewhere else                                                                       
 896             moveItemInDatabase(context, item, container, screenId, cellX, cellY);                        
 897         }                                                                                                
 898     }                                                                                                    
 899 =======                                                                                                  
 900                                         addNotAnimated, addAnimated, allAppsApps);                       
 901 >>>>>>> GitAnalyzerPlus_theirs                                                                           
 902                             }                                                                            
 903                         }                                                                                
 904                     });                                                                                  
 905                 }                                                                                        
 906             }                                                                                            
 907         };                                                                                               
 908         runOnWorkerThread(r);                                                                            
 909     }                                                                                                    
 910                                                                                                          
 911     public void unbindItemInfosAndClearQueuedBindRunnables() {                                           
 912         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 913             throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +     
 914                     "main thread");                                                                      
 915         }                                                                                                
 916                                                                                                          
 917         // Clear any deferred bind runnables                                                             
 918         synchronized (mDeferredBindRunnables) {                                                          
 919             mDeferredBindRunnables.clear();                                                              
 920         }                                                                                                
 921         // Remove any queued bind runnables                                                              
 922         mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);                                 
 923         // Unbind all the workspace items                                                                
 924         unbindWorkspaceItemsOnMainThread();                                                              
 925     }                                                                                                    
 926                                                                                                          
 927     /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */                        
 928     void unbindWorkspaceItemsOnMainThread() {                                                            
 929         // Ensure that we don't use the same workspace items data structure on the main thread           
 930         // by making a copy of workspace items first.                                                    
 931         final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();                         
 932         final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();                             
 933         synchronized (sBgLock) {                                                                         
 934             tmpWorkspaceItems.addAll(sBgWorkspaceItems);                                                 
 935             tmpAppWidgets.addAll(sBgAppWidgets);                                                         
 936         }                                                                                                
 937         Runnable r = new Runnable() {                                                                    
 938                 @Override                                                                                
 939                 public void run() {                                                                      
 940                    for (ItemInfo item : tmpWorkspaceItems) {                                             
 941                        item.unbind();                                                                    
 942                    }                                                                                     
 943                    for (ItemInfo item : tmpAppWidgets) {                                                 
 944                        item.unbind();                                                                    
 945                    }                                                                                     
 946                 }                                                                                        
 947             };                                                                                           
 948         runOnMainThread(r);                                                                              
 949     }                                                                                                    
 950                                                                                                          
 951     /**                                                                                                  
 952      * Adds an item to the DB if it was not created previously, or move it to a new                      
 953      * <container, screen, cellX, cellY>                                                                 
 954      */                                                                                                  
 955     static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,                  
 956             long screenId, int cellX, int cellY) {                                                       
 957         if (item.container == ItemInfo.NO_ID) {                                                          
 958             // From all apps                                                                             
 959             addItemToDatabase(context, item, container, screenId, cellX, cellY, false);                  
 960         } else {                                                                                         
 961             // From somewhere else                                                                       
 962             moveItemInDatabase(context, item, container, screenId, cellX, cellY);                        
 963         }                                                                                                
 964     }                                                                                                    
 965                                                                                                          
 966     static void checkItemInfoLocked(                                                                     
 967             final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {                    
 968         ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                                  
 969         if (modelItem != null && item != modelItem) {                                                    
 970             // check all the data is consistent                                                          
 971             if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {                     
 972                 ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;                                   
 973                 ShortcutInfo shortcut = (ShortcutInfo) item;                                             
 974                 if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&                  
 975                         modelShortcut.intent.filterEquals(shortcut.intent) &&                            
 976                         modelShortcut.id == shortcut.id &&                                               
 977                         modelShortcut.itemType == shortcut.itemType &&                                   
 978                         modelShortcut.container == shortcut.container &&                                 
 979                         modelShortcut.screenId == shortcut.screenId &&                                   
 980                         modelShortcut.cellX == shortcut.cellX &&                                         
 981                         modelShortcut.cellY == shortcut.cellY &&                                         
 982                         modelShortcut.spanX == shortcut.spanX &&                                         
 983                         modelShortcut.spanY == shortcut.spanY &&                                         
 984                         ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||                  
 985                         (modelShortcut.dropPos != null &&                                                
 986                                 shortcut.dropPos != null &&                                              
 987                                 modelShortcut.dropPos[0] == shortcut.dropPos[0] &&                       
 988                         modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {                             
 989                     // For all intents and purposes, this is the same object                             
 990                     return;                                                                              
 991                 }                                                                                        
 992             }                                                                                            
 993                                                                                                          
 994             // the modelItem needs to match up perfectly with item if our model is                       
 995             // to be consistent with the database-- for now, just require                                
 996             // modelItem == item or the equality check above                                             
 997             String msg = "item: " + ((item != null) ? item.toString() : "null") +                        
 998                     "modelItem: " +                                                                      
 999                     ((modelItem != null) ? modelItem.toString() : "null") +                              
1000                     "Error: ItemInfo passed to checkItemInfo doesn't match original";                    
1001             RuntimeException e = new RuntimeException(msg);                                              
1002             if (stackTrace != null) {                                                                    
1003                 e.setStackTrace(stackTrace);                                                             
1004             }                                                                                            
1005             throw e;                                                                                     
1006         }                                                                                                
1007     }                                                                                                    
1008                                                                                                          
1009     static void checkItemInfo(final ItemInfo item) {                                                     
1010         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
1011         final long itemId = item.id;                                                                     
1012         Runnable r = new Runnable() {                                                                    
1013             public void run() {                                                                          
1014                 synchronized (sBgLock) {                                                                 
1015                     checkItemInfoLocked(itemId, item, stackTrace);                                       
1016                 }                                                                                        
1017             }                                                                                            
1018         };                                                                                               
1019         runOnWorkerThread(r);                                                                            
1020     }                                                                                                    
1021                                                                                                          
1022     static void updateItemInDatabaseHelper(Context context, final ContentValues values,                  
1023             final ItemInfo item, final String callingFunction) {                                         
1024         final long itemId = item.id;                                                                     
1025         final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);                         
1026         final ContentResolver cr = context.getContentResolver();                                         
1027                                                                                                          
1028         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
1029         Runnable r = new Runnable() {                                                                    
1030             public void run() {                                                                          
1031                 cr.update(uri, values, null, null);                                                      
1032                 updateItemArrays(item, itemId, stackTrace);                                              
1033             }                                                                                            
1034         };                                                                                               
1035         runOnWorkerThread(r);                                                                            
1036     }                                                                                                    
1037                                                                                                          
1038     static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,  
1039             final ArrayList<ItemInfo> items, final String callingFunction) {                             
1040         final ContentResolver cr = context.getContentResolver();                                         
1041                                                                                                          
1042         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
1043         Runnable r = new Runnable() {                                                                    
1044             public void run() {                                                                          
1045                 ArrayList<ContentProviderOperation> ops =                                                
1046                         new ArrayList<ContentProviderOperation>();                                       
1047                 int count = items.size();                                                                
1048                 for (int i = 0; i < count; i++) {                                                        
1049                     ItemInfo item = items.get(i);                                                        
1050                     final long itemId = item.id;                                                         
1051                     final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);             
1052                     ContentValues values = valuesList.get(i);                                            
1053                                                                                                          
1054                     ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());         
1055                     updateItemArrays(item, itemId, stackTrace);                                          
1056                                                                                                          
1057                 }                                                                                        
1058                 try {                                                                                    
1059                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
1060                 } catch (Exception e) {                                                                  
1061                     e.printStackTrace();                                                                 
1062                 }                                                                                        
1063             }                                                                                            
1064         };                                                                                               
1065         runOnWorkerThread(r);                                                                            
1066     }                                                                                                    
1067                                                                                                          
1068     static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {           
1069         // Lock on mBgLock *after* the db operation                                                      
1070         synchronized (sBgLock) {                                                                         
1071             checkItemInfoLocked(itemId, item, stackTrace);                                               
1072                                                                                                          
1073             if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&                        
1074                     item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                    
1075                 // Item is in a folder, make sure this folder exists                                     
1076                 if (!sBgFolders.containsKey(item.container)) {                                           
1077                     // An items container is being set to a that of an item which is not in              
1078                     // the list of Folders.                                                              
1079                     String msg = "item: " + item + " container being set to: " +                         
1080                             item.container + ", not in the list of folders";                             
1081                     Log.e(TAG, msg);                                                                     
1082                 }                                                                                        
1083             }                                                                                            
1084                                                                                                          
1085             // Items are added/removed from the corresponding FolderInfo elsewhere, such                 
1086             // as in Workspace.onDrop. Here, we just add/remove them from the list of items              
1087             // that are on the desktop, as appropriate                                                   
1088             ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                              
1089             if (modelItem != null &&                                                                     
1090                     (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||              
1091                      modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {             
1092                 switch (modelItem.itemType) {                                                            
1093                     case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                               
1094                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                  
1095                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                    
1096                         if (!sBgWorkspaceItems.contains(modelItem)) {                                    
1097                             sBgWorkspaceItems.add(modelItem);                                            
1098                         }                                                                                
1099                         break;                                                                           
1100                     default:                                                                             
1101                         break;                                                                           
1102                 }                                                                                        
1103             } else {                                                                                     
1104                 sBgWorkspaceItems.remove(modelItem);                                                     
1105             }                                                                                            
1106         }                                                                                                
1107     }                                                                                                    
1108                                                                                                          
1109     public void flushWorkerThread() {                                                                    
1110         mFlushingWorkerThread = true;                                                                    
1111         Runnable waiter = new Runnable() {                                                               
1112                 public void run() {                                                                      
1113                     synchronized (this) {                                                                
1114                         notifyAll();                                                                     
1115                         mFlushingWorkerThread = false;                                                   
1116                     }                                                                                    
1117                 }                                                                                        
1118             };                                                                                           
1119                                                                                                          
1120         synchronized(waiter) {                                                                           
1121             runOnWorkerThread(waiter);                                                                   
1122             if (mLoaderTask != null) {                                                                   
1123                 synchronized(mLoaderTask) {                                                              
1124                     mLoaderTask.notify();                                                                
1125                 }                                                                                        
1126             }                                                                                            
1127             boolean success = false;                                                                     
1128             while (!success) {                                                                           
1129                 try {                                                                                    
1130                     waiter.wait();                                                                       
1131                     success = true;                                                                      
1132                 } catch (InterruptedException e) {                                                       
1133                 }                                                                                        
1134             }                                                                                            
1135         }                                                                                                
1136     }                                                                                                    
1137                                                                                                          
1138     /**                                                                                                  
1139      * Move an item in the DB to a new <container, screen, cellX, cellY>                                 
1140      */                                                                                                  
1141     static void moveItemInDatabase(Context context, final ItemInfo item, final long container,           
1142             final long screenId, final int cellX, final int cellY) {                                     
1143         item.container = container;                                                                      
1144         item.cellX = cellX;                                                                              
1145         item.cellY = cellY;                                                                              
1146                                                                                                          
1147         // We store hotseat items in canonical form which is this orientation invariant position         
1148         // in the hotseat                                                                                
1149         if (context instanceof Launcher && screenId < 0 &&                                               
1150                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
1151             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
1152         } else {                                                                                         
1153             item.screenId = screenId;                                                                    
1154         }                                                                                                
1155                                                                                                          
1156         final ContentValues values = new ContentValues();                                                
1157         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
1158         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
1159         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
1160         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
1161                                                                                                          
1162         updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");                         
1163     }                                                                                                    
1164                                                                                                          
1165     /**                                                                                                  
1166      * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the               
1167      * cellX, cellY have already been updated on the ItemInfos.                                          
1168      */                                                                                                  
1169     static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,                    
1170             final long container, final int screen) {                                                    
1171                                                                                                          
1172         ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();                         
1173         int count = items.size();                                                                        
1174                                                                                                          
1175         for (int i = 0; i < count; i++) {                                                                
1176             ItemInfo item = items.get(i);                                                                
1177             item.container = container;                                                                  
1178                                                                                                          
1179             // We store hotseat items in canonical form which is this orientation invariant position     
1180             // in the hotseat                                                                            
1181             if (context instanceof Launcher && screen < 0 &&                                             
1182                     container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                         
1183                 item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,          
1184                         item.cellY);                                                                     
1185             } else {                                                                                     
1186                 item.screenId = screen;                                                                  
1187             }                                                                                            
1188                                                                                                          
1189             final ContentValues values = new ContentValues();                                            
1190             values.put(LauncherSettings.Favorites.CONTAINER, item.container);                            
1191             values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                    
1192             values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                    
1193             values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                
1194                                                                                                          
1195             contentValues.add(values);                                                                   
1196         }                                                                                                
1197         updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");                
1198     }                                                                                                    
1199                                                                                                          
1200     /**                                                                                                  
1201      * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>        
1202      */                                                                                                  
1203     static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,         
1204             final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {   
1205         item.container = container;                                                                      
1206         item.cellX = cellX;                                                                              
1207         item.cellY = cellY;                                                                              
1208         item.spanX = spanX;                                                                              
1209         item.spanY = spanY;                                                                              
1210                                                                                                          
1211         // We store hotseat items in canonical form which is this orientation invariant position         
1212         // in the hotseat                                                                                
1213         if (context instanceof Launcher && screenId < 0 &&                                               
1214                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
1215             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
1216         } else {                                                                                         
1217             item.screenId = screenId;                                                                    
1218         }                                                                                                
1219                                                                                                          
1220         final ContentValues values = new ContentValues();                                                
1221         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
1222         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
1223         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
1224         values.put(LauncherSettings.Favorites.SPANX, item.spanX);                                        
1225         values.put(LauncherSettings.Favorites.SPANY, item.spanY);                                        
1226         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
1227                                                                                                          
1228         updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");                       
1229     }                                                                                                    
1230                                                                                                          
1231     /**                                                                                                  
1232      * Update an item to the database in a specified container.                                          
1233      */                                                                                                  
1234     static void updateItemInDatabase(Context context, final ItemInfo item) {                             
1235         final ContentValues values = new ContentValues();                                                
1236         item.onAddToDatabase(context, values);                                                           
1237         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
1238         updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");                       
1239     }                                                                                                    
1240                                                                                                          
1241     /**                                                                                                  
1242      * Returns true if the shortcuts already exists in the database.                                     
1243      * we identify a shortcut by its title and intent.                                                   
1244      */                                                                                                  
1245     static boolean shortcutExists(Context context, String title, Intent intent) {                        
1246         final ContentResolver cr = context.getContentResolver();                                         
1247         final Intent intentWithPkg, intentWithoutPkg;                                                    
1248                                                                                                          
1249         if (intent.getComponent() != null) {                                                             
1250             // If component is not null, an intent with null package will produce                        
1251             // the same result and should also be a match.                                               
1252             if (intent.getPackage() != null) {                                                           
1253                 intentWithPkg = intent;                                                                  
1254                 intentWithoutPkg = new Intent(intent).setPackage(null);                                  
1255             } else {                                                                                     
1256                 intentWithPkg = new Intent(intent).setPackage(                                           
1257                         intent.getComponent().getPackageName());                                         
1258                 intentWithoutPkg = intent;                                                               
1259             }                                                                                            
1260         } else {                                                                                         
1261             intentWithPkg = intent;                                                                      
1262             intentWithoutPkg = intent;                                                                   
1263         }                                                                                                
1264         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,                                      
1265             new String[] { "title", "intent" }, "title=? and (intent=? or intent=?)",                    
1266             new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0) }, null);            
1267         boolean result = false;                                                                          
1268         try {                                                                                            
1269             result = c.moveToFirst();                                                                    
1270         } finally {                                                                                      
1271             c.close();                                                                                   
1272         }                                                                                                
1273         return result;                                                                                   
1274     }                                                                                                    
1275                                                                                                          
1276     /**                                                                                                  
1277 <<<<<<< GitAnalyzerPlus_ours                                                                             
1278      * Returns true if the promise shortcuts with the same package name exists on the workspace.         
1279      */                                                                                                  
1280     static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {                
1281         final ComponentName component = intent.getComponent();                                           
1282         if (component == null) {                                                                         
1283             return false;                                                                                
1284         }                                                                                                
1285         return !getItemsByPackageName(component.getPackageName(), user).isEmpty();                       
1286     }                                                                                                    
1287                                                                                                          
1288     /**                                                                                                  
1289 ||||||| GitAnalyzerPlus_base                                                                             
1290         item.spanX = spanX;                                                                              
1291         item.spanY = spanY;                                                                              
1292                                                                                                          
1293         // We store hotseat items in canonical form which is this orientation invariant position         
1294         // in the hotseat                                                                                
1295         if (context instanceof Launcher && screenId < 0 &&                                               
1296                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
1297             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
1298         } else {                                                                                         
1299             item.screenId = screenId;                                                                    
1300         }                                                                                                
1301                                                                                                          
1302         final ContentValues values = new ContentValues();                                                
1303         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
1304         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
1305         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
1306         values.put(LauncherSettings.Favorites.SPANX, item.spanX);                                        
1307         values.put(LauncherSettings.Favorites.SPANY, item.spanY);                                        
1308         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
1309                                                                                                          
1310         updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");                       
1311     }                                                                                                    
1312                                                                                                          
1313     /**                                                                                                  
1314      * Update an item to the database in a specified container.                                          
1315      */                                                                                                  
1316     static void updateItemInDatabase(Context context, final ItemInfo item) {                             
1317         final ContentValues values = new ContentValues();                                                
1318         item.onAddToDatabase(values);                                                                    
1319         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
1320         updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");                       
1321     }                                                                                                    
1322                                                                                                          
1323     /**                                                                                                  
1324      * Returns true if the shortcuts already exists in the database.                                     
1325      * we identify a shortcut by its title and intent.                                                   
1326      */                                                                                                  
1327     static boolean shortcutExists(Context context, String title, Intent intent) {                        
1328         final ContentResolver cr = context.getContentResolver();                                         
1329         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,                                      
1330             new String[] { "title", "intent" }, "title=? and intent=?",                                  
1331             new String[] { title, intent.toUri(0) }, null);                                              
1332         boolean result = false;                                                                          
1333         try {                                                                                            
1334             result = c.moveToFirst();                                                                    
1335         } finally {                                                                                      
1336             c.close();                                                                                   
1337         }                                                                                                
1338         return result;                                                                                   
1339     }                                                                                                    
1340                                                                                                          
1341     /**                                                                                                  
1342      * Returns true if the shortcuts already exists in the database.                                     
1343      * we identify a shortcut by the component name of the intent.                                       
1344      */                                                                                                  
1345     static boolean appWasRestored(Context context, Intent intent) {                                      
1346         final ContentResolver cr = context.getContentResolver();                                         
1347         final ComponentName component = intent.getComponent();                                           
1348         if (component == null) {                                                                         
1349             return false;                                                                                
1350         }                                                                                                
1351         String componentName = component.flattenToString();                                              
1352         final String where = "intent glob \"*component=" + componentName + "*\" and restored = 1";       
1353         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,                                      
1354                 new String[]{"intent", "restored"}, where, null, null);                                  
1355         boolean result = false;                                                                          
1356         try {                                                                                            
1357             result = c.moveToFirst();                                                                    
1358         } finally {                                                                                      
1359             c.close();                                                                                   
1360         }                                                                                                
1361         Log.d(TAG, "shortcutWasRestored is " + result + " for " + componentName);                        
1362         return result;                                                                                   
1363     }                                                                                                    
1364                                                                                                          
1365     /**                                                                                                  
1366      * Returns an ItemInfo array containing all the items in the LauncherModel.                          
1367      * The ItemInfo.id is not set through this function.                                                 
1368      */                                                                                                  
1369     static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {                             
1370         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
1371         final ContentResolver cr = context.getContentResolver();                                         
1372         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {                       
1373                 LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,              
1374                 LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.CELLX, LauncherSettings.Fav🔵
1375                 LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY }, null, null, null); 
1376                                                                                                          
1377         final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);         
1378         final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);        
1379         final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);              
1380         final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                
1381         final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                
1382         final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);                
1383         final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);                
1384                                                                                                          
1385         try {                                                                                            
1386             while (c.moveToNext()) {                                                                     
1387                 ItemInfo item = new ItemInfo();                                                          
1388                 item.cellX = c.getInt(cellXIndex);                                                       
1389                 item.cellY = c.getInt(cellYIndex);                                                       
1390                 item.spanX = Math.max(1, c.getInt(spanXIndex));                                          
1391                 item.spanY = Math.max(1, c.getInt(spanYIndex));                                          
1392                 item.container = c.getInt(containerIndex);                                               
1393                 item.itemType = c.getInt(itemTypeIndex);                                                 
1394                 item.screenId = c.getInt(screenIndex);                                                   
1395                                                                                                          
1396                 items.add(item);                                                                         
1397             }                                                                                            
1398         } catch (Exception e) {                                                                          
1399             items.clear();                                                                               
1400         } finally {                                                                                      
1401             c.close();                                                                                   
1402         }                                                                                                
1403                                                                                                          
1404         return items;                                                                                    
1405     }                                                                                                    
1406                                                                                                          
1407     /**                                                                                                  
1408      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.       
1409      */                                                                                                  
1410     FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {            
1411         final ContentResolver cr = context.getContentResolver();                                         
1412         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,                                
1413                 "_id=? and (itemType=? or itemType=?)",                                                  
1414                 new String[] { String.valueOf(id),                                                       
1415                         String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);             
1416                                                                                                          
1417         try {                                                                                            
1418             if (c.moveToFirst()) {                                                                       
1419                 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); 
1420                 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);        
1421                 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
1422                 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);      
1423                 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);        
1424                 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);        
1425                                                                                                          
1426                 FolderInfo folderInfo = null;                                                            
1427                 switch (c.getInt(itemTypeIndex)) {                                                       
1428                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                    
1429                         folderInfo = findOrMakeFolder(folderList, id);                                   
1430                         break;                                                                           
1431                 }                                                                                        
1432                                                                                                          
1433 =======                                                                                                  
1434 >>>>>>> GitAnalyzerPlus_theirs                                                                           
1435      * Returns an ItemInfo array containing all the items in the LauncherModel.                          
1436      * The ItemInfo.id is not set through this function.                                                 
1437      */                                                                                                  
1438     static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {                             
1439         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
1440         final ContentResolver cr = context.getContentResolver();                                         
1441         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {                       
1442                 LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,              
1443                 LauncherSettings.Favorites.SCREEN,                                                       
1444                 LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,                      
1445                 LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY,                      
1446                 LauncherSettings.Favorites.PROFILE_ID }, null, null, null);                              
1447                                                                                                          
1448         final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);         
1449         final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);        
1450         final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);              
1451         final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                
1452         final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                
1453         final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);                
1454         final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);                
1455         final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);       
1456         UserManagerCompat userManager = UserManagerCompat.getInstance(context);                          
1457         try {                                                                                            
1458             while (c.moveToNext()) {                                                                     
1459                 ItemInfo item = new ItemInfo();                                                          
1460                 item.cellX = c.getInt(cellXIndex);                                                       
1461                 item.cellY = c.getInt(cellYIndex);                                                       
1462                 item.spanX = Math.max(1, c.getInt(spanXIndex));                                          
1463                 item.spanY = Math.max(1, c.getInt(spanYIndex));                                          
1464                 item.container = c.getInt(containerIndex);                                               
1465                 item.itemType = c.getInt(itemTypeIndex);                                                 
1466                 item.screenId = c.getInt(screenIndex);                                                   
1467                 long serialNumber = c.getInt(profileIdIndex);                                            
1468                 item.user = userManager.getUserForSerialNumber(serialNumber);                            
1469                 // Skip if user has been deleted.                                                        
1470                 if (item.user != null) {                                                                 
1471                     items.add(item);                                                                     
1472                 }                                                                                        
1473             }                                                                                            
1474         } catch (Exception e) {                                                                          
1475             items.clear();                                                                               
1476         } finally {                                                                                      
1477             c.close();                                                                                   
1478         }                                                                                                
1479                                                                                                          
1480         return items;                                                                                    
1481     }                                                                                                    
1482                                                                                                          
1483     /**                                                                                                  
1484      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.       
1485      */                                                                                                  
1486     FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {            
1487         final ContentResolver cr = context.getContentResolver();                                         
1488         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,                                
1489                 "_id=? and (itemType=? or itemType=?)",                                                  
1490                 new String[] { String.valueOf(id),                                                       
1491                         String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);             
1492                                                                                                          
1493         try {                                                                                            
1494             if (c.moveToFirst()) {                                                                       
1495                 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); 
1496                 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);        
1497                 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
1498                 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);      
1499                 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);        
1500                 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);        
1501                                                                                                          
1502                 FolderInfo folderInfo = null;                                                            
1503                 switch (c.getInt(itemTypeIndex)) {                                                       
1504                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                    
1505                         folderInfo = findOrMakeFolder(folderList, id);                                   
1506                         break;                                                                           
1507                 }                                                                                        
1508                                                                                                          
1509                 folderInfo.title = c.getString(titleIndex);                                              
1510                 folderInfo.id = id;                                                                      
1511                 folderInfo.container = c.getInt(containerIndex);                                         
1512                 folderInfo.screenId = c.getInt(screenIndex);                                             
1513                 folderInfo.cellX = c.getInt(cellXIndex);                                                 
1514                 folderInfo.cellY = c.getInt(cellYIndex);                                                 
1515                                                                                                          
1516                 return folderInfo;                                                                       
1517             }                                                                                            
1518         } finally {                                                                                      
1519             c.close();                                                                                   
1520         }                                                                                                
1521                                                                                                          
1522         return null;                                                                                     
1523     }                                                                                                    
1524                                                                                                          
1525     /**                                                                                                  
1526      * Add an item to the database in a specified container. Sets the container, screen, cellX and       
1527      * cellY fields of the item. Also assigns an ID to the item.                                         
1528      */                                                                                                  
1529     static void addItemToDatabase(Context context, final ItemInfo item, final long container,            
1530             final long screenId, final int cellX, final int cellY, final boolean notify) {               
1531         item.container = container;                                                                      
1532         item.cellX = cellX;                                                                              
1533         item.cellY = cellY;                                                                              
1534         // We store hotseat items in canonical form which is this orientation invariant position         
1535         // in the hotseat                                                                                
1536         if (context instanceof Launcher && screenId < 0 &&                                               
1537                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
1538             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
1539         } else {                                                                                         
1540             item.screenId = screenId;                                                                    
1541         }                                                                                                
1542                                                                                                          
1543         final ContentValues values = new ContentValues();                                                
1544         final ContentResolver cr = context.getContentResolver();                                         
1545         item.onAddToDatabase(context, values);                                                           
1546                                                                                                          
1547         item.id = LauncherAppState.getLauncherProvider().generateNewItemId();                            
1548         values.put(LauncherSettings.Favorites._ID, item.id);                                             
1549         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
1550                                                                                                          
1551         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
1552         Runnable r = new Runnable() {                                                                    
1553             public void run() {                                                                          
1554                 cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :                              
1555                         LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);                 
1556                                                                                                          
1557                 // Lock on mBgLock *after* the db operation                                              
1558                 synchronized (sBgLock) {                                                                 
1559                     checkItemInfoLocked(item.id, item, stackTrace);                                      
1560                     sBgItemsIdMap.put(item.id, item);                                                    
1561                     switch (item.itemType) {                                                             
1562                         case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                
1563                             sBgFolders.put(item.id, (FolderInfo) item);                                  
1564                             // Fall through                                                              
1565                         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                           
1566                         case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                              
1567                             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||        
1568                                     item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {    
1569                                 sBgWorkspaceItems.add(item);                                             
1570                             } else {                                                                     
1571                                 if (!sBgFolders.containsKey(item.container)) {                           
1572                                     // Adding an item to a folder that doesn't exist.                    
1573                                     String msg = "adding item: " + item + " to a folder that " +         
1574                                             " doesn't exist";                                            
1575                                     Log.e(TAG, msg);                                                     
1576                                 }                                                                        
1577                             }                                                                            
1578                             break;                                                                       
1579                         case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                             
1580                             sBgAppWidgets.add((LauncherAppWidgetInfo) item);                             
1581                             break;                                                                       
1582                     }                                                                                    
1583                 }                                                                                        
1584             }                                                                                            
1585         };                                                                                               
1586         runOnWorkerThread(r);                                                                            
1587     }                                                                                                    
1588                                                                                                          
1589     /**                                                                                                  
1590      * Creates a new unique child id, for a given cell span across all layouts.                          
1591      */                                                                                                  
1592     static int getCellLayoutChildId(                                                                     
1593             long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {         
1594         return (((int) container & 0xFF) << 24)                                                          
1595                 | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);          
1596     }                                                                                                    
1597                                                                                                          
1598     private static ArrayList<ItemInfo> getItemsByPackageName(                                            
1599             final String pn, final UserHandleCompat user) {                                              
1600         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
1601             @Override                                                                                    
1602             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
1603                 return cn.getPackageName().equals(pn) && info.user.equals(user);                         
1604             }                                                                                            
1605         };                                                                                               
1606         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
1607     }                                                                                                    
1608                                                                                                          
1609     /**                                                                                                  
1610      * Removes all the items from the database corresponding to the specified package.                   
1611      */                                                                                                  
1612     static void deletePackageFromDatabase(Context context, final String pn,                              
1613             final UserHandleCompat user) {                                                               
1614         deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));                               
1615     }                                                                                                    
1616                                                                                                          
1617     /**                                                                                                  
1618      * Removes the specified item from the database                                                      
1619      * @param context                                                                                    
1620      * @param item                                                                                       
1621      */                                                                                                  
1622     static void deleteItemFromDatabase(Context context, final ItemInfo item) {                           
1623         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
1624         items.add(item);                                                                                 
1625         deleteItemsFromDatabase(context, items);                                                         
1626     }                                                                                                    
1627                                                                                                          
1628     /**                                                                                                  
1629      * Removes the specified items from the database                                                     
1630      * @param context                                                                                    
1631      * @param item                                                                                       
1632      */                                                                                                  
1633     static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {              
1634         final ContentResolver cr = context.getContentResolver();                                         
1635                                                                                                          
1636         Runnable r = new Runnable() {                                                                    
1637             public void run() {                                                                          
1638                 for (ItemInfo item : items) {                                                            
1639                     final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);            
1640                     cr.delete(uri, null, null);                                                          
1641                                                                                                          
1642                     // Lock on mBgLock *after* the db operation                                          
1643                     synchronized (sBgLock) {                                                             
1644                         switch (item.itemType) {                                                         
1645                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                            
1646                                 sBgFolders.remove(item.id);                                              
1647                                 for (ItemInfo info: sBgItemsIdMap.values()) {                            
1648                                     if (info.container == item.id) {                                     
1649                                         // We are deleting a folder which still contains items that      
1650                                         // think they are contained by that folder.                      
1651                                         String msg = "deleting a folder (" + item + ") which still " +   
1652                                                 "contains items (" + info + ")";                         
1653                                         Log.e(TAG, msg);                                                 
1654                                     }                                                                    
1655                                 }                                                                        
1656                                 sBgWorkspaceItems.remove(item);                                          
1657                                 break;                                                                   
1658                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                       
1659                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                          
1660                                 sBgWorkspaceItems.remove(item);                                          
1661                                 break;                                                                   
1662                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                         
1663                                 sBgAppWidgets.remove((LauncherAppWidgetInfo) item);                      
1664                                 break;                                                                   
1665                         }                                                                                
1666                         sBgItemsIdMap.remove(item.id);                                                   
1667                         sBgDbIconCache.remove(item);                                                     
1668                     }                                                                                    
1669                 }                                                                                        
1670             }                                                                                            
1671         };                                                                                               
1672         runOnWorkerThread(r);                                                                            
1673     }                                                                                                    
1674                                                                                                          
1675     /**                                                                                                  
1676      * Update the order of the workspace screens in the database. The array list contains                
1677      * a list of screen ids in the order that they should appear.                                        
1678      */                                                                                                  
1679     void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {                    
1680         // Log to disk                                                                                   
1681         Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);                       
1682         Launcher.addDumpLog(TAG, "11683562 -   screens: " + TextUtils.join(", ", screens), true);        
1683                                                                                                          
1684         final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);                                
1685         final ContentResolver cr = context.getContentResolver();                                         
1686         final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                                   
1687                                                                                                          
1688         // Remove any negative screen ids -- these aren't persisted                                      
1689         Iterator<Long> iter = screensCopy.iterator();                                                    
1690         while (iter.hasNext()) {                                                                         
1691             long id = iter.next();                                                                       
1692             if (id < 0) {                                                                                
1693                 iter.remove();                                                                           
1694             }                                                                                            
1695         }                                                                                                
1696                                                                                                          
1697         Runnable r = new Runnable() {                                                                    
1698             @Override                                                                                    
1699             public void run() {                                                                          
1700                 ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();     
1701                 // Clear the table                                                                       
1702                 ops.add(ContentProviderOperation.newDelete(uri).build());                                
1703                 int count = screensCopy.size();                                                          
1704                 for (int i = 0; i < count; i++) {                                                        
1705                     ContentValues v = new ContentValues();                                               
1706                     long screenId = screensCopy.get(i);                                                  
1707                     v.put(LauncherSettings.WorkspaceScreens._ID, screenId);                              
1708                     v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);                             
1709                     ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());              
1710                 }                                                                                        
1711                                                                                                          
1712                 try {                                                                                    
1713                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
1714                 } catch (Exception ex) {                                                                 
1715                     throw new RuntimeException(ex);                                                      
1716                 }                                                                                        
1717                                                                                                          
1718                 synchronized (sBgLock) {                                                                 
1719                     sBgWorkspaceScreens.clear();                                                         
1720                     sBgWorkspaceScreens.addAll(screensCopy);                                             
1721                 }                                                                                        
1722             }                                                                                            
1723         };                                                                                               
1724         runOnWorkerThread(r);                                                                            
1725     }                                                                                                    
1726                                                                                                          
1727     /**                                                                                                  
1728      * Remove the contents of the specified folder from the database                                     
1729      */                                                                                                  
1730     static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {               
1731         final ContentResolver cr = context.getContentResolver();                                         
1732                                                                                                          
1733         Runnable r = new Runnable() {                                                                    
1734             public void run() {                                                                          
1735                 cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);         
1736                 // Lock on mBgLock *after* the db operation                                              
1737                 synchronized (sBgLock) {                                                                 
1738                     sBgItemsIdMap.remove(info.id);                                                       
1739                     sBgFolders.remove(info.id);                                                          
1740                     sBgDbIconCache.remove(info);                                                         
1741                     sBgWorkspaceItems.remove(info);                                                      
1742                 }                                                                                        
1743                                                                                                          
1744                 cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,                        
1745                         LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);                     
1746                 // Lock on mBgLock *after* the db operation                                              
1747                 synchronized (sBgLock) {                                                                 
1748                     for (ItemInfo childInfo : info.contents) {                                           
1749                         sBgItemsIdMap.remove(childInfo.id);                                              
1750                         sBgDbIconCache.remove(childInfo);                                                
1751                     }                                                                                    
1752                 }                                                                                        
1753             }                                                                                            
1754         };                                                                                               
1755         runOnWorkerThread(r);                                                                            
1756     }                                                                                                    
1757                                                                                                          
1758     /**                                                                                                  
1759      * Set this as the current Launcher activity object for the loader.                                  
1760      */                                                                                                  
1761     public void initialize(Callbacks callbacks) {                                                        
1762         synchronized (mLock) {                                                                           
1763             mCallbacks = new WeakReference<Callbacks>(callbacks);                                        
1764         }                                                                                                
1765     }                                                                                                    
1766                                                                                                          
1767     @Override                                                                                            
1768     public void onPackageChanged(String packageName, UserHandleCompat user) {                            
1769         int op = PackageUpdatedTask.OP_UPDATE;                                                           
1770         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1771                 user));                                                                                  
1772     }                                                                                                    
1773                                                                                                          
1774     @Override                                                                                            
1775     public void onPackageRemoved(String packageName, UserHandleCompat user) {                            
1776         int op = PackageUpdatedTask.OP_REMOVE;                                                           
1777         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1778                 user));                                                                                  
1779     }                                                                                                    
1780                                                                                                          
1781     @Override                                                                                            
1782     public void onPackageAdded(String packageName, UserHandleCompat user) {                              
1783         int op = PackageUpdatedTask.OP_ADD;                                                              
1784         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1785                 user));                                                                                  
1786     }                                                                                                    
1787                                                                                                          
1788     @Override                                                                                            
1789     public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,                        
1790             boolean replacing) {                                                                         
1791         if (!replacing) {                                                                                
1792             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames,        
1793                     user));                                                                              
1794             if (mAppsCanBeOnRemoveableStorage) {                                                         
1795                 // Only rebind if we support removable storage. It catches the                           
1796                 // case where                                                                            
1797                 // apps on the external sd card need to be reloaded                                      
1798                 startLoaderFromBackground();                                                             
1799             }                                                                                            
1800         } else {                                                                                         
1801             // If we are replacing then just update the packages in the list                             
1802             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,                   
1803                     packageNames, user));                                                                
1804         }                                                                                                
1805     }                                                                                                    
1806                                                                                                          
1807     @Override                                                                                            
1808     public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,                      
1809             boolean replacing) {                                                                         
1810         if (!replacing) {                                                                                
1811             enqueuePackageUpdated(new PackageUpdatedTask(                                                
1812                     PackageUpdatedTask.OP_UNAVAILABLE, packageNames,                                     
1813                     user));                                                                              
1814         }                                                                                                
1815                                                                                                          
1816     }                                                                                                    
1817                                                                                                          
1818     /**                                                                                                  
1819      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and                        
1820      * ACTION_PACKAGE_CHANGED.                                                                           
1821      */                                                                                                  
1822     @Override                                                                                            
1823     public void onReceive(Context context, Intent intent) {                                              
1824         if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);                                    
1825                                                                                                          
1826         final String action = intent.getAction();                                                        
1827         if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {                                               
1828             // If we have changed locale we need to clear out the labels in all apps/workspace.          
1829             forceReload();                                                                               
1830         } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {                                 
1831              // Check if configuration change was an mcc/mnc change which would affect app resources     
1832              // and we would need to clear out the labels in all apps/workspace. Same handling as        
1833              // above for ACTION_LOCALE_CHANGED                                                          
1834              Configuration currentConfig = context.getResources().getConfiguration();                    
1835              if (mPreviousConfigMcc != currentConfig.mcc) {                                              
1836                    Log.d(TAG, "Reload apps on config change. curr_mcc:"                                  
1837                        + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);                          
1838                    forceReload();                                                                        
1839              }                                                                                           
1840              // Update previousConfig                                                                    
1841              mPreviousConfigMcc = currentConfig.mcc;                                                     
1842         } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) ||                 
1843                    SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)) {                     
1844             if (mCallbacks != null) {                                                                    
1845                 Callbacks callbacks = mCallbacks.get();                                                  
1846                 if (callbacks != null) {                                                                 
1847                     callbacks.bindSearchablesChanged();                                                  
1848                 }                                                                                        
1849             }                                                                                            
1850         }                                                                                                
1851     }                                                                                                    
1852                                                                                                          
1853     void forceReload() {                                                                                 
1854         resetLoadedState(true, true);                                                                    
1855                                                                                                          
1856         // Do this here because if the launcher activity is running it will be restarted.                
1857         // If it's not running startLoaderFromBackground will merely tell it that it needs               
1858         // to reload.                                                                                    
1859         startLoaderFromBackground();                                                                     
1860     }                                                                                                    
1861                                                                                                          
1862     public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {             
1863         synchronized (mLock) {                                                                           
1864             // Stop any existing loaders first, so they don't set mAllAppsLoaded or                      
1865             // mWorkspaceLoaded to true later                                                            
1866             stopLoaderLocked();                                                                          
1867             if (resetAllAppsLoaded) mAllAppsLoaded = false;                                              
1868             if (resetWorkspaceLoaded) mWorkspaceLoaded = false;                                          
1869         }                                                                                                
1870     }                                                                                                    
1871                                                                                                          
1872     /**                                                                                                  
1873      * When the launcher is in the background, it's possible for it to miss paired                       
1874      * configuration changes.  So whenever we trigger the loader from the background                     
1875      * tell the launcher that it needs to re-run the loader when it comes back instead                   
1876      * of doing it now.                                                                                  
1877      */                                                                                                  
1878     public void startLoaderFromBackground() {                                                            
1879         boolean runLoader = false;                                                                       
1880         if (mCallbacks != null) {                                                                        
1881             Callbacks callbacks = mCallbacks.get();                                                      
1882             if (callbacks != null) {                                                                     
1883                 // Only actually run the loader if they're not paused.                                   
1884                 if (!callbacks.setLoadOnResume()) {                                                      
1885                     runLoader = true;                                                                    
1886                 }                                                                                        
1887             }                                                                                            
1888         }                                                                                                
1889         if (runLoader) {                                                                                 
1890             startLoader(false, PagedView.INVALID_RESTORE_PAGE);                                          
1891         }                                                                                                
1892     }                                                                                                    
1893                                                                                                          
1894     // If there is already a loader task running, tell it to stop.                                       
1895     // returns true if isLaunching() was true on the old task                                            
1896     private boolean stopLoaderLocked() {                                                                 
1897         boolean isLaunching = false;                                                                     
1898         LoaderTask oldTask = mLoaderTask;                                                                
1899         if (oldTask != null) {                                                                           
1900             if (oldTask.isLaunching()) {                                                                 
1901                 isLaunching = true;                                                                      
1902             }                                                                                            
1903             oldTask.stopLocked();                                                                        
1904         }                                                                                                
1905         return isLaunching;                                                                              
1906     }                                                                                                    
1907                                                                                                          
1908     public boolean isCurrentCallbacks(Callbacks callbacks) {                                             
1909         return (mCallbacks != null && mCallbacks.get() == callbacks);                                    
1910     }                                                                                                    
1911                                                                                                          
1912     public void startLoader(boolean isLaunching, int synchronousBindPage) {                              
1913         startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);                                 
1914     }                                                                                                    
1915                                                                                                          
1916     public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {               
1917         synchronized (mLock) {                                                                           
1918             if (DEBUG_LOADERS) {                                                                         
1919                 Log.d(TAG, "startLoader isLaunching=" + isLaunching);                                    
1920             }                                                                                            
1921                                                                                                          
1922             // Clear any deferred bind-runnables from the synchronized load process                      
1923             // We must do this before any loading/binding is scheduled below.                            
1924             synchronized (mDeferredBindRunnables) {                                                      
1925                 mDeferredBindRunnables.clear();                                                          
1926             }                                                                                            
1927                                                                                                          
1928             // Don't bother to start the thread if we know it's not going to do anything                 
1929             if (mCallbacks != null && mCallbacks.get() != null) {                                        
1930                 // If there is already one running, tell it to stop.                                     
1931                 // also, don't downgrade isLaunching if we're already running                            
1932                 isLaunching = isLaunching || stopLoaderLocked();                                         
1933                 mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);                 
1934                 if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE                                
1935                         && mAllAppsLoaded && mWorkspaceLoaded) {                                         
1936                     mLoaderTask.runBindSynchronousPage(synchronousBindPage);                             
1937                 } else {                                                                                 
1938                     sWorkerThread.setPriority(Thread.NORM_PRIORITY);                                     
1939                     sWorker.post(mLoaderTask);                                                           
1940                 }                                                                                        
1941             }                                                                                            
1942         }                                                                                                
1943     }                                                                                                    
1944                                                                                                          
1945     void bindRemainingSynchronousPages() {                                                               
1946         // Post the remaining side pages to be loaded                                                    
1947         if (!mDeferredBindRunnables.isEmpty()) {                                                         
1948             Runnable[] deferredBindRunnables = null;                                                     
1949             synchronized (mDeferredBindRunnables) {                                                      
1950                 deferredBindRunnables = mDeferredBindRunnables.toArray(                                  
1951                         new Runnable[mDeferredBindRunnables.size()]);                                    
1952                 mDeferredBindRunnables.clear();                                                          
1953             }                                                                                            
1954             for (final Runnable r : deferredBindRunnables) {                                             
1955                 mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);                                          
1956             }                                                                                            
1957         }                                                                                                
1958     }                                                                                                    
1959                                                                                                          
1960     public void stopLoader() {                                                                           
1961         synchronized (mLock) {                                                                           
1962             if (mLoaderTask != null) {                                                                   
1963                 mLoaderTask.stopLocked();                                                                
1964             }                                                                                            
1965         }                                                                                                
1966     }                                                                                                    
1967                                                                                                          
1968     /** Loads the workspace screens db into a map of Rank -> ScreenId */                                 
1969     private static TreeMap<Integer, Long> loadWorkspaceScreensDb(Context context) {                      
1970         final ContentResolver contentResolver = context.getContentResolver();                            
1971         final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                            
1972         final Cursor sc = contentResolver.query(screensUri, null, null, null, null);                     
1973         TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();                            
1974                                                                                                          
1975         try {                                                                                            
1976             final int idIndex = sc.getColumnIndexOrThrow(                                                
1977                     LauncherSettings.WorkspaceScreens._ID);                                              
1978             final int rankIndex = sc.getColumnIndexOrThrow(                                              
1979                     LauncherSettings.WorkspaceScreens.SCREEN_RANK);                                      
1980             while (sc.moveToNext()) {                                                                    
1981                 try {                                                                                    
1982                     long screenId = sc.getLong(idIndex);                                                 
1983                     int rank = sc.getInt(rankIndex);                                                     
1984                     orderedScreens.put(rank, screenId);                                                  
1985                 } catch (Exception e) {                                                                  
1986                     Launcher.addDumpLog(TAG, "Desktop items loading interrupted - invalid screens: " + e,🔵
1987                 }                                                                                        
1988             }                                                                                            
1989         } finally {                                                                                      
1990             sc.close();                                                                                  
1991         }                                                                                                
1992                                                                                                          
1993         // Log to disk                                                                                   
1994         Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);                           
1995         ArrayList<String> orderedScreensPairs= new ArrayList<String>();                                  
1996         for (Integer i : orderedScreens.keySet()) {                                                      
1997             orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }");                     
1998         }                                                                                                
1999         Launcher.addDumpLog(TAG, "11683562 -   screens: " +                                              
2000                 TextUtils.join(", ", orderedScreensPairs), true);                                        
2001         return orderedScreens;                                                                           
2002     }                                                                                                    
2003                                                                                                          
2004     public boolean isAllAppsLoaded() {                                                                   
2005         return mAllAppsLoaded;                                                                           
2006     }                                                                                                    
2007                                                                                                          
2008     boolean isLoadingWorkspace() {                                                                       
2009         synchronized (mLock) {                                                                           
2010             if (mLoaderTask != null) {                                                                   
2011                 return mLoaderTask.isLoadingWorkspace();                                                 
2012             }                                                                                            
2013         }                                                                                                
2014         return false;                                                                                    
2015     }                                                                                                    
2016                                                                                                          
2017     /**                                                                                                  
2018      * Runnable for the thread that loads the contents of the launcher:                                  
2019      *   - workspace icons                                                                               
2020      *   - widgets                                                                                       
2021      *   - all apps icons                                                                                
2022      */                                                                                                  
2023     private class LoaderTask implements Runnable {                                                       
2024         private Context mContext;                                                                        
2025         private boolean mIsLaunching;                                                                    
2026         private boolean mIsLoadingAndBindingWorkspace;                                                   
2027         private boolean mStopped;                                                                        
2028         private boolean mLoadAndBindStepFinished;                                                        
2029         private int mFlags;                                                                              
2030                                                                                                          
2031         private HashMap<Object, CharSequence> mLabelCache;                                               
2032                                                                                                          
2033         LoaderTask(Context context, boolean isLaunching, int flags) {                                    
2034             mContext = context;                                                                          
2035             mIsLaunching = isLaunching;                                                                  
2036             mLabelCache = new HashMap<Object, CharSequence>();                                           
2037             mFlags = flags;                                                                              
2038         }                                                                                                
2039                                                                                                          
2040         boolean isLaunching() {                                                                          
2041             return mIsLaunching;                                                                         
2042         }                                                                                                
2043                                                                                                          
2044         boolean isLoadingWorkspace() {                                                                   
2045             return mIsLoadingAndBindingWorkspace;                                                        
2046         }                                                                                                
2047                                                                                                          
2048         /** Returns whether this is an upgrade path */                                                   
2049         private boolean loadAndBindWorkspace() {                                                         
2050             mIsLoadingAndBindingWorkspace = true;                                                        
2051                                                                                                          
2052             // Load the workspace                                                                        
2053             if (DEBUG_LOADERS) {                                                                         
2054                 Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);                 
2055             }                                                                                            
2056                                                                                                          
2057             boolean isUpgradePath = false;                                                               
2058             if (!mWorkspaceLoaded) {                                                                     
2059                 isUpgradePath = loadWorkspace();                                                         
2060                 synchronized (LoaderTask.this) {                                                         
2061                     if (mStopped) {                                                                      
2062                         return isUpgradePath;                                                            
2063                     }                                                                                    
2064                     mWorkspaceLoaded = true;                                                             
2065                 }                                                                                        
2066             }                                                                                            
2067                                                                                                          
2068             // Bind the workspace                                                                        
2069             bindWorkspace(-1, isUpgradePath);                                                            
2070             return isUpgradePath;                                                                        
2071         }                                                                                                
2072                                                                                                          
2073         private void waitForIdle() {                                                                     
2074             // Wait until the either we're stopped or the other threads are done.                        
2075             // This way we don't start loading all apps until the workspace has settled                  
2076             // down.                                                                                     
2077             synchronized (LoaderTask.this) {                                                             
2078                 final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;           
2079                                                                                                          
2080                 mHandler.postIdle(new Runnable() {                                                       
2081                         public void run() {                                                              
2082                             synchronized (LoaderTask.this) {                                             
2083                                 mLoadAndBindStepFinished = true;                                         
2084                                 if (DEBUG_LOADERS) {                                                     
2085                                     Log.d(TAG, "done with previous binding step");                       
2086                                 }                                                                        
2087                                 LoaderTask.this.notify();                                                
2088                             }                                                                            
2089                         }                                                                                
2090                     });                                                                                  
2091                                                                                                          
2092                 while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) {               
2093                     try {                                                                                
2094                         // Just in case mFlushingWorkerThread changes but we aren't woken up,            
2095                         // wait no longer than 1sec at a time                                            
2096                         this.wait(1000);                                                                 
2097                     } catch (InterruptedException ex) {                                                  
2098                         // Ignore                                                                        
2099                     }                                                                                    
2100                 }                                                                                        
2101                 if (DEBUG_LOADERS) {                                                                     
2102                     Log.d(TAG, "waited "                                                                 
2103                             + (SystemClock.uptimeMillis()-workspaceWaitTime)                             
2104                             + "ms for previous step to finish binding");                                 
2105                 }                                                                                        
2106             }                                                                                            
2107         }                                                                                                
2108                                                                                                          
2109         void runBindSynchronousPage(int synchronousBindPage) {                                           
2110             if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {                                 
2111                 // Ensure that we have a valid page index to load synchronously                          
2112                 throw new RuntimeException("Should not call runBindSynchronousPage() without " +         
2113                         "valid page index");                                                             
2114             }                                                                                            
2115             if (!mAllAppsLoaded || !mWorkspaceLoaded) {                                                  
2116                 // Ensure that we don't try and bind a specified page when the pages have not been       
2117                 // loaded already (we should load everything asynchronously in that case)                
2118                 throw new RuntimeException("Expecting AllApps and Workspace to be loaded");              
2119             }                                                                                            
2120             synchronized (mLock) {                                                                       
2121                 if (mIsLoaderTaskRunning) {                                                              
2122                     // Ensure that we are never running the background loading at this point since       
2123                     // we also touch the background collections                                          
2124                     throw new RuntimeException("Error! Background loading is already running");          
2125                 }                                                                                        
2126             }                                                                                            
2127                                                                                                          
2128             // XXX: Throw an exception if we are already loading (since we touch the worker thread       
2129             //      data structures, we can't allow any other thread to touch that data, but because     
2130             //      this call is synchronous, we can get away with not locking).                         
2131                                                                                                          
2132             // The LauncherModel is static in the LauncherAppState and mHandler may have queued          
2133             // operations from the previous activity.  We need to ensure that all queued operations      
2134             // are executed before any synchronous binding work is done.                                 
2135             mHandler.flush();                                                                            
2136                                                                                                          
2137             // Divide the set of loaded items into those that we are binding synchronously, and          
2138             // everything else that is to be bound normally (asynchronously).                            
2139             bindWorkspace(synchronousBindPage, false);                                                   
2140             // XXX: For now, continue posting the binding of AllApps as there are other issues that      
2141             //      arise from that.                                                                     
2142             onlyBindAllApps();                                                                           
2143         }                                                                                                
2144                                                                                                          
2145         public void run() {                                                                              
2146             boolean isUpgrade = false;                                                                   
2147                                                                                                          
2148             synchronized (mLock) {                                                                       
2149                 mIsLoaderTaskRunning = true;                                                             
2150             }                                                                                            
2151             // Optimize for end-user experience: if the Launcher is up and // running with the           
2152             // All Apps interface in the foreground, load All Apps first. Otherwise, load the            
2153             // workspace first (default).                                                                
2154             keep_running: {                                                                              
2155                 // Elevate priority when Home launches for the first time to avoid                       
2156                 // starving at boot time. Staring at a blank home is not cool.                           
2157                 synchronized (mLock) {                                                                   
2158                     if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +                        
2159                             (mIsLaunching ? "DEFAULT" : "BACKGROUND"));                                  
2160                     android.os.Process.setThreadPriority(mIsLaunching                                    
2161                             ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);     
2162                 }                                                                                        
2163                 if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");                              
2164                 isUpgrade = loadAndBindWorkspace();                                                      
2165                                                                                                          
2166                 if (mStopped) {                                                                          
2167                     break keep_running;                                                                  
2168                 }                                                                                        
2169                                                                                                          
2170                 // Whew! Hard work done.  Slow us down, and wait until the UI thread has                 
2171                 // settled down.                                                                         
2172                 synchronized (mLock) {                                                                   
2173                     if (mIsLaunching) {                                                                  
2174                         if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");          
2175                         android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);        
2176                     }                                                                                    
2177                 }                                                                                        
2178                 waitForIdle();                                                                           
2179                                                                                                          
2180                 // second step                                                                           
2181                 if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");                               
2182                 loadAndBindAllApps();                                                                    
2183                                                                                                          
2184                 // Restore the default thread priority after we are done loading items                   
2185                 synchronized (mLock) {                                                                   
2186                     android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);               
2187                 }                                                                                        
2188             }                                                                                            
2189                                                                                                          
2190             // Update the saved icons if necessary                                                       
2191             if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");                   
2192             synchronized (sBgLock) {                                                                     
2193                 for (Object key : sBgDbIconCache.keySet()) {                                             
2194                     updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));              
2195                 }                                                                                        
2196                 sBgDbIconCache.clear();                                                                  
2197             }                                                                                            
2198                                                                                                          
2199             if (LauncherAppState.isDisableAllApps()) {                                                   
2200                 // Ensure that all the applications that are in the system are                           
2201                 // represented on the home screen.                                                       
2202                 if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {                                       
2203                     verifyApplications();                                                                
2204                 }                                                                                        
2205             }                                                                                            
2206                                                                                                          
2207             // Clear out this reference, otherwise we end up holding it until all of the                 
2208             // callback runnables are done.                                                              
2209             mContext = null;                                                                             
2210                                                                                                          
2211             synchronized (mLock) {                                                                       
2212                 // If we are still the last one to be scheduled, remove ourselves.                       
2213                 if (mLoaderTask == this) {                                                               
2214                     mLoaderTask = null;                                                                  
2215                 }                                                                                        
2216                 mIsLoaderTaskRunning = false;                                                            
2217             }                                                                                            
2218         }                                                                                                
2219                                                                                                          
2220         public void stopLocked() {                                                                       
2221             synchronized (LoaderTask.this) {                                                             
2222                 mStopped = true;                                                                         
2223                 this.notify();                                                                           
2224             }                                                                                            
2225         }                                                                                                
2226                                                                                                          
2227         /**                                                                                              
2228          * Gets the callbacks object.  If we've been stopped, or if the launcher object                  
2229          * has somehow been garbage collected, return null instead.  Pass in the Callbacks               
2230          * object that was around when the deferred message was scheduled, and if there's                
2231          * a new Callbacks object around then also return null.  This will save us from                  
2232          * calling onto it with data that will be ignored.                                               
2233          */                                                                                              
2234         Callbacks tryGetCallbacks(Callbacks oldCallbacks) {                                              
2235             synchronized (mLock) {                                                                       
2236                 if (mStopped) {                                                                          
2237                     return null;                                                                         
2238                 }                                                                                        
2239                                                                                                          
2240                 if (mCallbacks == null) {                                                                
2241                     return null;                                                                         
2242                 }                                                                                        
2243                                                                                                          
2244                 final Callbacks callbacks = mCallbacks.get();                                            
2245                 if (callbacks != oldCallbacks) {                                                         
2246                     return null;                                                                         
2247                 }                                                                                        
2248                 if (callbacks == null) {                                                                 
2249                     Log.w(TAG, "no mCallbacks");                                                         
2250                     return null;                                                                         
2251                 }                                                                                        
2252                                                                                                          
2253                 return callbacks;                                                                        
2254             }                                                                                            
2255         }                                                                                                
2256                                                                                                          
2257         private void verifyApplications() {                                                              
2258             final Context context = mApp.getContext();                                                   
2259                                                                                                          
2260             // Cross reference all the applications in our apps list with items in the workspace         
2261             ArrayList<ItemInfo> tmpInfos;                                                                
2262             ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();                                       
2263             synchronized (sBgLock) {                                                                     
2264                 for (AppInfo app : mBgAllAppsList.data) {                                                
2265                     tmpInfos = getItemInfoForComponentName(app.componentName, app.user);                 
2266                     if (tmpInfos.isEmpty()) {                                                            
2267                         // We are missing an application icon, so add this to the workspace              
2268                         added.add(app);                                                                  
2269                         // This is a rare event, so lets log it                                          
2270                         Log.e(TAG, "Missing Application on load: " + app);                               
2271                     }                                                                                    
2272                 }                                                                                        
2273             }                                                                                            
2274             if (!added.isEmpty()) {                                                                      
2275                 addAndBindAddedWorkspaceApps(context, added);                                            
2276             }                                                                                            
2277         }                                                                                                
2278                                                                                                          
2279         // check & update map of what's occupied; used to discard overlapping/invalid items              
2280         private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,          
2281                                            AtomicBoolean deleteOnInvalidPlacement) {                     
2282             LauncherAppState app = LauncherAppState.getInstance();                                       
2283             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
2284             final int countX = (int) grid.numColumns;                                                    
2285             final int countY = (int) grid.numRows;                                                       
2286                                                                                                          
2287             long containerIndex = item.screenId;                                                         
2288             if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                        
2289                 // Return early if we detect that an item is under the hotseat button                    
2290                 if (mCallbacks == null ||                                                                
2291                         mCallbacks.get().isAllAppsButtonRank((int) item.screenId)) {                     
2292                     deleteOnInvalidPlacement.set(true);                                                  
2293                     Log.e(TAG, "Error loading shortcut into hotseat " + item                             
2294                             + " into position (" + item.screenId + ":" + item.cellX + ","                
2295                             + item.cellY + ") occupied by all apps");                                    
2296                     return false;                                                                        
2297                 }                                                                                        
2298                                                                                                          
2299                 final ItemInfo[][] hotseatItems =                                                        
2300                         occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);               
2301                                                                                                          
2302                 if (item.screenId >= grid.numHotseatIcons) {                                             
2303                     Log.e(TAG, "Error loading shortcut " + item                                          
2304                             + " into hotseat position " + item.screenId                                  
2305                             + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)            
2306                             + ")");                                                                      
2307                     return false;                                                                        
2308                 }                                                                                        
2309                                                                                                          
2310                 if (hotseatItems != null) {                                                              
2311                     if (hotseatItems[(int) item.screenId][0] != null) {                                  
2312                         Log.e(TAG, "Error loading shortcut into hotseat " + item                         
2313                                 + " into position (" + item.screenId + ":" + item.cellX + ","            
2314                                 + item.cellY + ") occupied by "                                          
2315                                 + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)             
2316                                 [(int) item.screenId][0]);                                               
2317                             return false;                                                                
2318                     } else {                                                                             
2319                         hotseatItems[(int) item.screenId][0] = item;                                     
2320                         return true;                                                                     
2321                     }                                                                                    
2322                 } else {                                                                                 
2323                     final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];              
2324                     items[(int) item.screenId][0] = item;                                                
2325                     occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);            
2326                     return true;                                                                         
2327                 }                                                                                        
2328             } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {                 
2329                 // Skip further checking if it is not the hotseat or workspace container                 
2330                 return true;                                                                             
2331             }                                                                                            
2332                                                                                                          
2333             if (!occupied.containsKey(item.screenId)) {                                                  
2334                 ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];                               
2335                 occupied.put(item.screenId, items);                                                      
2336             }                                                                                            
2337                                                                                                          
2338             final ItemInfo[][] screens = occupied.get(item.screenId);                                    
2339             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                        
2340                     item.cellX < 0 || item.cellY < 0 ||                                                  
2341                     item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {              
2342                 Log.e(TAG, "Error loading shortcut " + item                                              
2343                         + " into cell (" + containerIndex + "-" + item.screenId + ":"                    
2344                         + item.cellX + "," + item.cellY                                                  
2345                         + ") out of screen bounds ( " + countX + "x" + countY + ")");                    
2346                 return false;                                                                            
2347             }                                                                                            
2348                                                                                                          
2349             // Check if any workspace icons overlap with each other                                      
2350             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                 
2351                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                             
2352                     if (screens[x][y] != null) {                                                         
2353                         Log.e(TAG, "Error loading shortcut " + item                                      
2354                             + " into cell (" + containerIndex + "-" + item.screenId + ":"                
2355                             + x + "," + y                                                                
2356                             + ") occupied by "                                                           
2357                             + screens[x][y]);                                                            
2358                         return false;                                                                    
2359                     }                                                                                    
2360                 }                                                                                        
2361             }                                                                                            
2362             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                 
2363                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                             
2364                     screens[x][y] = item;                                                                
2365                 }                                                                                        
2366             }                                                                                            
2367                                                                                                          
2368             return true;                                                                                 
2369         }                                                                                                
2370                                                                                                          
2371         /** Clears all the sBg data structures */                                                        
2372         private void clearSBgDataStructures() {                                                          
2373             synchronized (sBgLock) {                                                                     
2374                 sBgWorkspaceItems.clear();                                                               
2375                 sBgAppWidgets.clear();                                                                   
2376                 sBgFolders.clear();                                                                      
2377                 sBgItemsIdMap.clear();                                                                   
2378                 sBgDbIconCache.clear();                                                                  
2379                 sBgWorkspaceScreens.clear();                                                             
2380             }                                                                                            
2381         }                                                                                                
2382                                                                                                          
2383         /** Returns whether this is an upgrade path */                                                   
2384         private boolean loadWorkspace() {                                                                
2385             // Log to disk                                                                               
2386             Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);                                
2387                                                                                                          
2388             final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                               
2389                                                                                                          
2390             final Context context = mContext;                                                            
2391             final ContentResolver contentResolver = context.getContentResolver();                        
2392             final PackageManager manager = context.getPackageManager();                                  
2393             final AppWidgetManager widgets = AppWidgetManager.getInstance(context);                      
2394             final boolean isSafeMode = manager.isSafeMode();                                             
2395             final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);             
2396             final boolean isSdCardReady = context.registerReceiver(null,                                 
2397                     new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;                             
2398                                                                                                          
2399             LauncherAppState app = LauncherAppState.getInstance();                                       
2400             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
2401             int countX = (int) grid.numColumns;                                                          
2402             int countY = (int) grid.numRows;                                                             
2403                                                                                                          
2404             if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {                                           
2405                 Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);            
2406                 LauncherAppState.getLauncherProvider().deleteDatabase();                                 
2407             }                                                                                            
2408                                                                                                          
2409             if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {                                         
2410                 // append the user's Launcher2 shortcuts                                                 
2411                 Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);               
2412                 LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();                      
2413             } else {                                                                                     
2414                 // Make sure the default workspace is loaded                                             
2415                 Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);             
2416                 LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();                
2417             }                                                                                            
2418                                                                                                          
2419             // This code path is for our old migration code and should no longer be exercised            
2420             boolean loadedOldDb = false;                                                                 
2421                                                                                                          
2422             // Log to disk                                                                               
2423             Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);                  
2424                                                                                                          
2425             synchronized (sBgLock) {                                                                     
2426                 clearSBgDataStructures();                                                                
2427                 final HashSet<String> installingPkgs = PackageInstallerCompat                            
2428                         .getInstance(mContext).updateAndGetActiveSessionCache();                         
2429                                                                                                          
2430                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();                             
2431                 final ArrayList<Long> restoredRows = new ArrayList<Long>();                              
2432                 final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;           
2433                 if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);                       
2434                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);              
2435                                                                                                          
2436                 // +1 for the hotseat (it can be larger than the workspace)                              
2437                 // Load workspace in reverse order to ensure that latest items are loaded first (and     
2438                 // before any earlier duplicates)                                                        
2439                 final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();          
2440                                                                                                          
2441                 try {                                                                                    
2442                     final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);         
2443                     final int intentIndex = c.getColumnIndexOrThrow                                      
2444                             (LauncherSettings.Favorites.INTENT);                                         
2445                     final int titleIndex = c.getColumnIndexOrThrow                                       
2446                             (LauncherSettings.Favorites.TITLE);                                          
2447                     final int iconTypeIndex = c.getColumnIndexOrThrow(                                   
2448                             LauncherSettings.Favorites.ICON_TYPE);                                       
2449                     final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);      
2450                     final int iconPackageIndex = c.getColumnIndexOrThrow(                                
2451                             LauncherSettings.Favorites.ICON_PACKAGE);                                    
2452                     final int iconResourceIndex = c.getColumnIndexOrThrow(                               
2453                             LauncherSettings.Favorites.ICON_RESOURCE);                                   
2454                     final int containerIndex = c.getColumnIndexOrThrow(                                  
2455                             LauncherSettings.Favorites.CONTAINER);                                       
2456                     final int itemTypeIndex = c.getColumnIndexOrThrow(                                   
2457                             LauncherSettings.Favorites.ITEM_TYPE);                                       
2458                     final int appWidgetIdIndex = c.getColumnIndexOrThrow(                                
2459                             LauncherSettings.Favorites.APPWIDGET_ID);                                    
2460                     final int appWidgetProviderIndex = c.getColumnIndexOrThrow(                          
2461                             LauncherSettings.Favorites.APPWIDGET_PROVIDER);                              
2462                     final int screenIndex = c.getColumnIndexOrThrow(                                     
2463                             LauncherSettings.Favorites.SCREEN);                                          
2464                     final int cellXIndex = c.getColumnIndexOrThrow                                       
2465                             (LauncherSettings.Favorites.CELLX);                                          
2466                     final int cellYIndex = c.getColumnIndexOrThrow                                       
2467                             (LauncherSettings.Favorites.CELLY);                                          
2468                     final int spanXIndex = c.getColumnIndexOrThrow                                       
2469                             (LauncherSettings.Favorites.SPANX);                                          
2470                     final int spanYIndex = c.getColumnIndexOrThrow(                                      
2471                             LauncherSettings.Favorites.SPANY);                                           
2472                     final int restoredIndex = c.getColumnIndexOrThrow(                                   
2473                             LauncherSettings.Favorites.RESTORED);                                        
2474                     final int profileIdIndex = c.getColumnIndexOrThrow(                                  
2475                             LauncherSettings.Favorites.PROFILE_ID);                                      
2476                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);      
2477                     //final int displayModeIndex = c.getColumnIndexOrThrow(                              
2478                     //        LauncherSettings.Favorites.DISPLAY_MODE);                                  
2479                                                                                                          
2480                     ShortcutInfo info;                                                                   
2481                     String intentDescription;                                                            
2482                     LauncherAppWidgetInfo appWidgetInfo;                                                 
2483                     int container;                                                                       
2484                     long id;                                                                             
2485                     Intent intent;                                                                       
2486                     UserHandleCompat user;                                                               
2487                                                                                                          
2488                     while (!mStopped && c.moveToNext()) {                                                
2489                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);               
2490                         try {                                                                            
2491                             int itemType = c.getInt(itemTypeIndex);                                      
2492                             boolean restored = 0 != c.getInt(restoredIndex);                             
2493                             boolean allowMissingTarget = false;                                          
2494                                                                                                          
2495                             switch (itemType) {                                                          
2496                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                       
2497                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                          
2498                                 id = c.getLong(idIndex);                                                 
2499                                 intentDescription = c.getString(intentIndex);                            
2500                                 long serialNumber = c.getInt(profileIdIndex);                            
2501                                 user = mUserManager.getUserForSerialNumber(serialNumber);                
2502                                 int promiseType = c.getInt(restoredIndex);                               
2503                                 if (user == null) {                                                      
2504                                     // User has been deleted remove the item.                            
2505                                     itemsToRemove.add(id);                                               
2506                                     continue;                                                            
2507                                 }                                                                        
2508                                 try {                                                                    
2509                                     intent = Intent.parseUri(intentDescription, 0);                      
2510                                     ComponentName cn = intent.getComponent();                            
2511                                     if (cn != null && cn.getPackageName() != null) {                     
2512                                         boolean validPkg = launcherApps.isPackageEnabledForProfile(      
2513                                                 cn.getPackageName(), user);                              
2514                                         boolean validComponent = validPkg &&                             
2515                                                 launcherApps.isActivityEnabledForProfile(cn, user);      
2516                                                                                                          
2517                                         if (validComponent) {                                            
2518                                             if (restored) {                                              
2519                                                 // no special handling necessary for this item           
2520                                                 restoredRows.add(id);                                    
2521                                                 restored = false;                                        
2522                                             }                                                            
2523                                         } else if (validPkg) {                                           
2524                                             intent = null;                                               
2525                                             if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
2526                                                 // We allow auto install apps to have their intent       
2527                                                 // updated after an install.                             
2528                                                 intent = manager.getLaunchIntentForPackage(              
2529                                                         cn.getPackageName());                            
2530                                                 if (intent != null) {                                    
2531                                                     ContentValues values = new ContentValues();          
2532                                                     values.put(LauncherSettings.Favorites.INTENT,        
2533                                                             intent.toUri(0));                            
2534                                                     String where = BaseColumns._ID + "= ?";              
2535                                                     String[] args = {Long.toString(id)};                 
2536                                                     contentResolver.update(contentUri, values, where, arg🔵
2537                                                 }                                                        
2538                                             }                                                            
2539                                                                                                          
2540                                             if (intent == null) {                                        
2541                                                 // The app is installed but the component is no          
2542                                                 // longer available.                                     
2543                                                 Launcher.addDumpLog(TAG,                                 
2544                                                         "Invalid component removed: " + cn, true);       
2545                                                 itemsToRemove.add(id);                                   
2546                                                 continue;                                                
2547                                             } else {                                                     
2548                                                 // no special handling necessary for this item           
2549                                                 restoredRows.add(id);                                    
2550                                                 restored = false;                                        
2551                                             }                                                            
2552                                         } else if (restored) {                                           
2553                                             // Package is not yet available but might be                 
2554                                             // installed later.                                          
2555                                             Launcher.addDumpLog(TAG,                                     
2556                                                     "package not yet restored: " + cn, true);            
2557                                                                                                          
2558                                             if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
2559                                                 // Restore has started once.                             
2560                                             } else if (installingPkgs.contains(cn.getPackageName())) {   
2561                                                 // App restore has started. Update the flag              
2562                                                 promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;        
2563                                                 ContentValues values = new ContentValues();              
2564                                                 values.put(LauncherSettings.Favorites.RESTORED,          
2565                                                         promiseType);                                    
2566                                                 String where = BaseColumns._ID + "= ?";                  
2567                                                 String[] args = {Long.toString(id)};                     
2568                                                 contentResolver.update(contentUri, values, where, args); 
2569                                                                                                          
2570                                             } else if (REMOVE_UNRESTORED_ICONS) {                        
2571                                                 Launcher.addDumpLog(TAG,                                 
2572                                                         "Unrestored package removed: " + cn, true);      
2573                                                 itemsToRemove.add(id);                                   
2574                                                 continue;                                                
2575                                             }                                                            
2576                                         } else if (isSdCardReady) {                                      
2577                                             // Do not wait for external media load anymore.              
2578                                             // Log the invalid package, and remove it                    
2579                                             Launcher.addDumpLog(TAG,                                     
2580                                                     "Invalid package removed: " + cn, true);             
2581                                             itemsToRemove.add(id);                                       
2582                                             continue;                                                    
2583                                         } else {                                                         
2584                                             // SdCard is not ready yet. Package might get available,     
2585                                             // once it is ready.                                         
2586                                             Launcher.addDumpLog(TAG, "Invalid package: " + cn            
2587                                                     + " (check again later)", true);                     
2588                                             HashSet<String> pkgs = sPendingPackages.get(user);           
2589                                             if (pkgs == null) {                                          
2590                                                 pkgs = new HashSet<String>();                            
2591                                                 sPendingPackages.put(user, pkgs);                        
2592                                             }                                                            
2593                                             pkgs.add(cn.getPackageName());                               
2594                                             allowMissingTarget = true;                                   
2595                                             // Add the icon on the workspace anyway.                     
2596                                         }                                                                
2597                                     } else if (cn == null) {                                             
2598                                         // For shortcuts with no component, keep them as they are        
2599                                         restoredRows.add(id);                                            
2600                                         restored = false;                                                
2601                                     }                                                                    
2602                                 } catch (URISyntaxException e) {                                         
2603                                     Launcher.addDumpLog(TAG,                                             
2604                                             "Invalid uri: " + intentDescription, true);                  
2605                                     continue;                                                            
2606                                 }                                                                        
2607                                                                                                          
2608                                 if (restored) {                                                          
2609 <<<<<<< GitAnalyzerPlus_ours                                                                             
2610                                     if (user.equals(UserHandleCompat.myUserHandle())) {                  
2611                                         Launcher.addDumpLog(TAG,                                         
2612                                                 "constructing info for partially restored package",      
2613                                                 true);                                                   
2614                                         info = getRestoredItemInfo(c, titleIndex, intent, promiseType);  
2615                                         intent = getRestoredItemIntent(c, context, intent);              
2616                                     } else {                                                             
2617                                         // Don't restore items for other profiles.                       
2618                                         itemsToRemove.add(id);                                           
2619                                         continue;                                                        
2620                                     }                                                                    
2621 ||||||| GitAnalyzerPlus_base                                                                             
2622                             LauncherSettings.Favorites.CONTAINER);                                       
2623                     final int itemTypeIndex = c.getColumnIndexOrThrow(                                   
2624                             LauncherSettings.Favorites.ITEM_TYPE);                                       
2625                     final int appWidgetIdIndex = c.getColumnIndexOrThrow(                                
2626                             LauncherSettings.Favorites.APPWIDGET_ID);                                    
2627                     final int appWidgetProviderIndex = c.getColumnIndexOrThrow(                          
2628                             LauncherSettings.Favorites.APPWIDGET_PROVIDER);                              
2629                     final int screenIndex = c.getColumnIndexOrThrow(                                     
2630                             LauncherSettings.Favorites.SCREEN);                                          
2631                     final int cellXIndex = c.getColumnIndexOrThrow                                       
2632                             (LauncherSettings.Favorites.CELLX);                                          
2633                     final int cellYIndex = c.getColumnIndexOrThrow                                       
2634                             (LauncherSettings.Favorites.CELLY);                                          
2635                     final int spanXIndex = c.getColumnIndexOrThrow                                       
2636                             (LauncherSettings.Favorites.SPANX);                                          
2637                     final int spanYIndex = c.getColumnIndexOrThrow(                                      
2638                             LauncherSettings.Favorites.SPANY);                                           
2639                     final int restoredIndex = c.getColumnIndexOrThrow(                                   
2640                             LauncherSettings.Favorites.RESTORED);                                        
2641                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);      
2642                     //final int displayModeIndex = c.getColumnIndexOrThrow(                              
2643                     //        LauncherSettings.Favorites.DISPLAY_MODE);                                  
2644                                                                                                          
2645                     ShortcutInfo info;                                                                   
2646                     String intentDescription;                                                            
2647                     LauncherAppWidgetInfo appWidgetInfo;                                                 
2648                     int container;                                                                       
2649                     long id;                                                                             
2650                     Intent intent;                                                                       
2651                                                                                                          
2652                     while (!mStopped && c.moveToNext()) {                                                
2653                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);               
2654                         try {                                                                            
2655                             int itemType = c.getInt(itemTypeIndex);                                      
2656                             boolean restored = 0 != c.getInt(restoredIndex);                             
2657                                                                                                          
2658                             switch (itemType) {                                                          
2659                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                       
2660                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                          
2661                                 id = c.getLong(idIndex);                                                 
2662                                 intentDescription = c.getString(intentIndex);                            
2663                                 try {                                                                    
2664                                     intent = Intent.parseUri(intentDescription, 0);                      
2665                                     ComponentName cn = intent.getComponent();                            
2666                                     if (cn != null && !isValidPackageComponent(manager, cn)) {           
2667                                         if (restored) {                                                  
2668                                             // might be installed later                                  
2669                                             Launcher.addDumpLog(TAG,                                     
2670                                                     "package not yet restored: " + cn, true);            
2671                                         } else {                                                         
2672                                             if (!mAppsCanBeOnRemoveableStorage) {                        
2673                                                 // Log the invalid package, and remove it                
2674                                                 Launcher.addDumpLog(TAG,                                 
2675                                                         "Invalid package removed: " + cn, true);         
2676                                                 itemsToRemove.add(id);                                   
2677                                             } else {                                                     
2678                                                 // If apps can be on external storage, then we just      
2679                                                 // leave them for the user to remove (maybe add          
2680                                                 // visual treatment to it)                               
2681                                                 Launcher.addDumpLog(TAG,                                 
2682                                                         "Invalid package found: " + cn, true);           
2683                                             }                                                            
2684                                             continue;                                                    
2685                                         }                                                                
2686                                     } else if (restored) {                                               
2687                                         // no special handling necessary for this restored item          
2688                                         restoredRows.add(id);                                            
2689                                         restored = false;                                                
2690                                     }                                                                    
2691                                 } catch (URISyntaxException e) {                                         
2692                                     Launcher.addDumpLog(TAG,                                             
2693                                             "Invalid uri: " + intentDescription, true);                  
2694                                     continue;                                                            
2695                                 }                                                                        
2696                                                                                                          
2697                                 if (restored) {                                                          
2698                                     Launcher.addDumpLog(TAG,                                             
2699                                             "constructing info for partially restored package",          
2700                                             true);                                                       
2701                                     info = getRestoredItemInfo(c, titleIndex, intent);                   
2702                                     intent = getRestoredItemIntent(c, context, intent);                  
2703                                 } else if (itemType ==                                                   
2704                                         LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {              
2705                                     info = getShortcutInfo(manager, intent, context, c, iconIndex,       
2706                                             titleIndex, mLabelCache);                                    
2707                                 } else {                                                                 
2708                                     info = getShortcutInfo(c, context, iconTypeIndex,                    
2709                                             iconPackageIndex, iconResourceIndex, iconIndex,              
2710                                             titleIndex);                                                 
2711                                                                                                          
2712                                     // App shortcuts that used to be automatically added to Launcher     
2713                                     // didn't always have the correct intent flags set, so do that       
2714                                     // here                                                              
2715                                     if (intent.getAction() != null &&                                    
2716                                         intent.getCategories() != null &&                                
2717                                         intent.getAction().equals(Intent.ACTION_MAIN) &&                 
2718                                         intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {     
2719                                         intent.addFlags(                                                 
2720                                             Intent.FLAG_ACTIVITY_NEW_TASK |                              
2721                                             Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);                  
2722                                     }                                                                    
2723                                 }                                                                        
2724                                                                                                          
2725                                 if (info != null) {                                                      
2726                                     info.id = id;                                                        
2727                                     info.intent = intent;                                                
2728                                     container = c.getInt(containerIndex);                                
2729                                     info.container = container;                                          
2730                                     info.screenId = c.getInt(screenIndex);                               
2731                                     info.cellX = c.getInt(cellXIndex);                                   
2732                                     info.cellY = c.getInt(cellYIndex);                                   
2733                                     info.spanX = 1;                                                      
2734                                     info.spanY = 1;                                                      
2735                                                                                                          
2736                                     // check & update map of what's occupied                             
2737                                     deleteOnInvalidPlacement.set(false);                                 
2738                                     if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) { 
2739                                         if (deleteOnInvalidPlacement.get()) {                            
2740                                             itemsToRemove.add(id);                                       
2741                                         }                                                                
2742                                         break;                                                           
2743                                     }                                                                    
2744                                                                                                          
2745                                     switch (container) {                                                 
2746                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
2747                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
2748                                         sBgWorkspaceItems.add(info);                                     
2749                                         break;                                                           
2750                                     default:                                                             
2751                                         // Item is in a user folder                                      
2752                                         FolderInfo folderInfo =                                          
2753                                                 findOrMakeFolder(sBgFolders, container);                 
2754                                         folderInfo.add(info);                                            
2755                                         break;                                                           
2756                                     }                                                                    
2757                                     sBgItemsIdMap.put(info.id, info);                                    
2758                                                                                                          
2759                                     // now that we've loaded everthing re-save it with the               
2760                                     // icon in case it disappears somehow.                               
2761                                     queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);            
2762                                 } else {                                                                 
2763                                     throw new RuntimeException("Unexpected null ShortcutInfo");          
2764                                 }                                                                        
2765                                 break;                                                                   
2766                                                                                                          
2767                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                            
2768                                 id = c.getLong(idIndex);                                                 
2769                                 FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);                
2770                                                                                                          
2771                                 folderInfo.title = c.getString(titleIndex);                              
2772                                 folderInfo.id = id;                                                      
2773                                 container = c.getInt(containerIndex);                                    
2774                                 folderInfo.container = container;                                        
2775                                 folderInfo.screenId = c.getInt(screenIndex);                             
2776                                 folderInfo.cellX = c.getInt(cellXIndex);                                 
2777                                 folderInfo.cellY = c.getInt(cellYIndex);                                 
2778                                 folderInfo.spanX = 1;                                                    
2779                                 folderInfo.spanY = 1;                                                    
2780                                                                                                          
2781                                 // check & update map of what's occupied                                 
2782                                 deleteOnInvalidPlacement.set(false);                                     
2783                                 if (!checkItemPlacement(occupied, folderInfo,                            
2784                                         deleteOnInvalidPlacement)) {                                     
2785                                     if (deleteOnInvalidPlacement.get()) {                                
2786                                         itemsToRemove.add(id);                                           
2787                                     }                                                                    
2788                                     break;                                                               
2789                                 }                                                                        
2790                                                                                                          
2791                                 switch (container) {                                                     
2792                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
2793                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
2794                                         sBgWorkspaceItems.add(folderInfo);                               
2795                                         break;                                                           
2796                                 }                                                                        
2797                                                                                                          
2798                                 if (restored) {                                                          
2799                                     // no special handling required for restored folders                 
2800                                     restoredRows.add(id);                                                
2801                                 }                                                                        
2802                                                                                                          
2803                                 sBgItemsIdMap.put(folderInfo.id, folderInfo);                            
2804                                 sBgFolders.put(folderInfo.id, folderInfo);                               
2805                                 break;                                                                   
2806                                                                                                          
2807                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                         
2808                                 // Read all Launcher-specific widget details                             
2809                                 int appWidgetId = c.getInt(appWidgetIdIndex);                            
2810                                 String savedProvider = c.getString(appWidgetProviderIndex);              
2811                                                                                                          
2812                                 id = c.getLong(idIndex);                                                 
2813                                                                                                          
2814                                 final AppWidgetProviderInfo provider =                                   
2815                                         widgets.getAppWidgetInfo(appWidgetId);                           
2816                                                                                                          
2817                                 if (!isSafeMode && (provider == null || provider.provider == null ||     
2818                                         provider.provider.getPackageName() == null)) {                   
2819                                     String log = "Deleting widget that isn't installed anymore: id="     
2820                                         + id + " appWidgetId=" + appWidgetId;                            
2821                                     Log.e(TAG, log);                                                     
2822                                     Launcher.addDumpLog(TAG, log, false);                                
2823                                     itemsToRemove.add(id);                                               
2824                                 } else {                                                                 
2825                                     appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,               
2826                                             provider.provider);                                          
2827                                     appWidgetInfo.id = id;                                               
2828                                     appWidgetInfo.screenId = c.getInt(screenIndex);                      
2829                                     appWidgetInfo.cellX = c.getInt(cellXIndex);                          
2830                                     appWidgetInfo.cellY = c.getInt(cellYIndex);                          
2831                                     appWidgetInfo.spanX = c.getInt(spanXIndex);                          
2832                                     appWidgetInfo.spanY = c.getInt(spanYIndex);                          
2833                                     int[] minSpan = Launcher.getMinSpanForWidget(context, provider);     
2834                                     appWidgetInfo.minSpanX = minSpan[0];                                 
2835                                     appWidgetInfo.minSpanY = minSpan[1];                                 
2836                                                                                                          
2837                                     container = c.getInt(containerIndex);                                
2838                                     if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&     
2839                                         container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {     
2840                                         Log.e(TAG, "Widget found where container != " +                  
2841                                             "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");      
2842                                         continue;                                                        
2843                                     }                                                                    
2844                                                                                                          
2845                                     appWidgetInfo.container = c.getInt(containerIndex);                  
2846                                     // check & update map of what's occupied                             
2847                                     deleteOnInvalidPlacement.set(false);                                 
2848                                     if (!checkItemPlacement(occupied, appWidgetInfo,                     
2849                                             deleteOnInvalidPlacement)) {                                 
2850                                         if (deleteOnInvalidPlacement.get()) {                            
2851                                             itemsToRemove.add(id);                                       
2852                                         }                                                                
2853                                         break;                                                           
2854                                     }                                                                    
2855                                     String providerName = provider.provider.flattenToString();           
2856                                     if (!providerName.equals(savedProvider)) {                           
2857                                         ContentValues values = new ContentValues();                      
2858                                         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,        
2859                                                 providerName);                                           
2860                                         String where = BaseColumns._ID + "= ?";                          
2861                                         String[] args = {Integer.toString(c.getInt(idIndex))};           
2862                                         contentResolver.update(contentUri, values, where, args);         
2863                                     }                                                                    
2864                                     sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);                  
2865                                     sBgAppWidgets.add(appWidgetInfo);                                    
2866                                 }                                                                        
2867                                 break;                                                                   
2868                             }                                                                            
2869                         } catch (Exception e) {                                                          
2870                             Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);      
2871                         }                                                                                
2872                     }                                                                                    
2873                 } finally {                                                                              
2874                     if (c != null) {                                                                     
2875                         c.close();                                                                       
2876                     }                                                                                    
2877                 }                                                                                        
2878                                                                                                          
2879                 // Break early if we've stopped loading                                                  
2880                 if (mStopped) {                                                                          
2881                     clearSBgDataStructures();                                                            
2882                     return false;                                                                        
2883                 }                                                                                        
2884                                                                                                          
2885                 if (itemsToRemove.size() > 0) {                                                          
2886                     ContentProviderClient client = contentResolver.acquireContentProviderClient(         
2887                             LauncherSettings.Favorites.CONTENT_URI);                                     
2888                     // Remove dead items                                                                 
2889                     for (long id : itemsToRemove) {                                                      
2890                         if (DEBUG_LOADERS) {                                                             
2891                             Log.d(TAG, "Removed id = " + id);                                            
2892                         }                                                                                
2893                         // Don't notify content observers                                                
2894                         try {                                                                            
2895                             client.delete(LauncherSettings.Favorites.getContentUri(id, false),           
2896                                     null, null);                                                         
2897                         } catch (RemoteException e) {                                                    
2898                             Log.w(TAG, "Could not remove id = " + id);                                   
2899                         }                                                                                
2900                     }                                                                                    
2901                 }                                                                                        
2902                                                                                                          
2903                 if (restoredRows.size() > 0) {                                                           
2904                     ContentProviderClient updater = contentResolver.acquireContentProviderClient(        
2905                             LauncherSettings.Favorites.CONTENT_URI);                                     
2906 =======                                                                                                  
2907                                     Launcher.addDumpLog(TAG,                                             
2908                                             "constructing info for partially restored package",          
2909                                             true);                                                       
2910                                     info = getRestoredItemInfo(c, titleIndex);                           
2911                                     intent = getRestoredItemIntent(c, context, intent);                  
2912 >>>>>>> GitAnalyzerPlus_theirs                                                                           
2913                                 } else if (itemType ==                                                   
2914                                         LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {              
2915                                     info = getShortcutInfo(manager, intent, user, context, c,            
2916                                             iconIndex, titleIndex, mLabelCache, allowMissingTarget);     
2917                                 } else {                                                                 
2918                                     info = getShortcutInfo(c, context, iconTypeIndex,                    
2919                                             iconPackageIndex, iconResourceIndex, iconIndex,              
2920                                             titleIndex);                                                 
2921                                                                                                          
2922                                     // App shortcuts that used to be automatically added to Launcher     
2923                                     // didn't always have the correct intent flags set, so do that       
2924                                     // here                                                              
2925                                     if (intent.getAction() != null &&                                    
2926                                         intent.getCategories() != null &&                                
2927                                         intent.getAction().equals(Intent.ACTION_MAIN) &&                 
2928                                         intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {     
2929                                         intent.addFlags(                                                 
2930                                             Intent.FLAG_ACTIVITY_NEW_TASK |                              
2931                                             Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);                  
2932                                     }                                                                    
2933                                 }                                                                        
2934                                                                                                          
2935                                 if (info != null) {                                                      
2936                                     info.id = id;                                                        
2937                                     info.intent = intent;                                                
2938                                     container = c.getInt(containerIndex);                                
2939                                     info.container = container;                                          
2940                                     info.screenId = c.getInt(screenIndex);                               
2941                                     info.cellX = c.getInt(cellXIndex);                                   
2942                                     info.cellY = c.getInt(cellYIndex);                                   
2943                                     info.spanX = 1;                                                      
2944                                     info.spanY = 1;                                                      
2945                                     info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);          
2946                                     info.isDisabled = isSafeMode                                         
2947                                             && !Utilities.isSystemApp(context, intent);                  
2948                                                                                                          
2949                                     // check & update map of what's occupied                             
2950                                     deleteOnInvalidPlacement.set(false);                                 
2951                                     if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) { 
2952                                         if (deleteOnInvalidPlacement.get()) {                            
2953                                             itemsToRemove.add(id);                                       
2954                                         }                                                                
2955                                         break;                                                           
2956                                     }                                                                    
2957                                                                                                          
2958                                     switch (container) {                                                 
2959                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
2960                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
2961                                         sBgWorkspaceItems.add(info);                                     
2962                                         break;                                                           
2963                                     default:                                                             
2964                                         // Item is in a user folder                                      
2965                                         FolderInfo folderInfo =                                          
2966                                                 findOrMakeFolder(sBgFolders, container);                 
2967                                         folderInfo.add(info);                                            
2968                                         break;                                                           
2969                                     }                                                                    
2970                                     sBgItemsIdMap.put(info.id, info);                                    
2971                                                                                                          
2972                                     // now that we've loaded everthing re-save it with the               
2973                                     // icon in case it disappears somehow.                               
2974                                     queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);            
2975                                 } else {                                                                 
2976                                     throw new RuntimeException("Unexpected null ShortcutInfo");          
2977                                 }                                                                        
2978                                 break;                                                                   
2979                                                                                                          
2980                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                            
2981                                 id = c.getLong(idIndex);                                                 
2982                                 FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);                
2983                                                                                                          
2984                                 folderInfo.title = c.getString(titleIndex);                              
2985                                 folderInfo.id = id;                                                      
2986                                 container = c.getInt(containerIndex);                                    
2987                                 folderInfo.container = container;                                        
2988                                 folderInfo.screenId = c.getInt(screenIndex);                             
2989                                 folderInfo.cellX = c.getInt(cellXIndex);                                 
2990                                 folderInfo.cellY = c.getInt(cellYIndex);                                 
2991                                 folderInfo.spanX = 1;                                                    
2992                                 folderInfo.spanY = 1;                                                    
2993                                                                                                          
2994                                 // check & update map of what's occupied                                 
2995                                 deleteOnInvalidPlacement.set(false);                                     
2996                                 if (!checkItemPlacement(occupied, folderInfo,                            
2997                                         deleteOnInvalidPlacement)) {                                     
2998                                     if (deleteOnInvalidPlacement.get()) {                                
2999                                         itemsToRemove.add(id);                                           
3000                                     }                                                                    
3001                                     break;                                                               
3002                                 }                                                                        
3003                                                                                                          
3004                                 switch (container) {                                                     
3005                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
3006                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
3007                                         sBgWorkspaceItems.add(folderInfo);                               
3008                                         break;                                                           
3009                                 }                                                                        
3010                                                                                                          
3011                                 if (restored) {                                                          
3012                                     // no special handling required for restored folders                 
3013                                     restoredRows.add(id);                                                
3014                                 }                                                                        
3015                                                                                                          
3016                                 sBgItemsIdMap.put(folderInfo.id, folderInfo);                            
3017                                 sBgFolders.put(folderInfo.id, folderInfo);                               
3018                                 break;                                                                   
3019                                                                                                          
3020                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                         
3021                                 // Read all Launcher-specific widget details                             
3022                                 int appWidgetId = c.getInt(appWidgetIdIndex);                            
3023                                 String savedProvider = c.getString(appWidgetProviderIndex);              
3024                                 id = c.getLong(idIndex);                                                 
3025                                 final ComponentName component =                                          
3026                                         ComponentName.unflattenFromString(savedProvider);                
3027                                                                                                          
3028                                 final int restoreStatus = c.getInt(restoredIndex);                       
3029                                 final boolean isIdValid = (restoreStatus &                               
3030                                         LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;                   
3031                                                                                                          
3032                                 final boolean wasProviderReady = (restoreStatus &                        
3033                                         LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;             
3034                                                                                                          
3035                                 final AppWidgetProviderInfo provider = isIdValid                         
3036                                         ? widgets.getAppWidgetInfo(appWidgetId)                          
3037                                         : findAppWidgetProviderInfoWithComponent(context, component);    
3038                                                                                                          
3039                                 final boolean isProviderReady = isValidProvider(provider);               
3040                                 if (!isSafeMode && wasProviderReady && !isProviderReady) {               
3041                                     String log = "Deleting widget that isn't installed anymore: "        
3042                                             + "id=" + id + " appWidgetId=" + appWidgetId;                
3043                                     Log.e(TAG, log);                                                     
3044                                     Launcher.addDumpLog(TAG, log, false);                                
3045                                     itemsToRemove.add(id);                                               
3046                                 } else {                                                                 
3047                                     if (isProviderReady) {                                               
3048                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,           
3049                                                 provider.provider);                                      
3050                                         int[] minSpan =                                                  
3051                                                 Launcher.getMinSpanForWidget(context, provider);         
3052                                         appWidgetInfo.minSpanX = minSpan[0];                             
3053                                         appWidgetInfo.minSpanY = minSpan[1];                             
3054                                                                                                          
3055                                         int status = restoreStatus;                                      
3056                                         if (!wasProviderReady) {                                         
3057                                             // If provider was not previously ready, update the          
3058                                             // status and UI flag.                                       
3059                                                                                                          
3060                                             // Id would be valid only if the widget restore broadcast was🔵
3061                                             if (isIdValid) {                                             
3062                                                 status = LauncherAppWidgetInfo.RESTORE_COMPLETED;        
3063                                             } else {                                                     
3064                                                 status &= ~LauncherAppWidgetInfo                         
3065                                                         .FLAG_PROVIDER_NOT_READY;                        
3066                                             }                                                            
3067                                         }                                                                
3068                                         appWidgetInfo.restoreStatus = status;                            
3069                                     } else {                                                             
3070                                         Log.v(TAG, "Widget restore pending id=" + id                     
3071                                                 + " appWidgetId=" + appWidgetId                          
3072                                                 + " status =" + restoreStatus);                          
3073                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,           
3074                                                 component);                                              
3075                                         appWidgetInfo.restoreStatus = restoreStatus;                     
3076                                                                                                          
3077                                         if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) 🔵
3078                                             // Restore has started once.                                 
3079                                         } else if (installingPkgs.contains(component.getPackageName())) {
3080                                             // App restore has started. Update the flag                  
3081                                             appWidgetInfo.restoreStatus |=                               
3082                                                     LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;          
3083                                         } else if (REMOVE_UNRESTORED_ICONS) {                            
3084                                             Launcher.addDumpLog(TAG,                                     
3085                                                     "Unrestored widget removed: " + component, true);    
3086                                             itemsToRemove.add(id);                                       
3087                                             continue;                                                    
3088                                         }                                                                
3089                                     }                                                                    
3090                                                                                                          
3091                                     appWidgetInfo.id = id;                                               
3092                                     appWidgetInfo.screenId = c.getInt(screenIndex);                      
3093                                     appWidgetInfo.cellX = c.getInt(cellXIndex);                          
3094                                     appWidgetInfo.cellY = c.getInt(cellYIndex);                          
3095                                     appWidgetInfo.spanX = c.getInt(spanXIndex);                          
3096                                     appWidgetInfo.spanY = c.getInt(spanYIndex);                          
3097                                                                                                          
3098                                     container = c.getInt(containerIndex);                                
3099                                     if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&     
3100                                         container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {     
3101                                         Log.e(TAG, "Widget found where container != " +                  
3102                                             "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");      
3103                                         continue;                                                        
3104                                     }                                                                    
3105                                                                                                          
3106                                     appWidgetInfo.container = c.getInt(containerIndex);                  
3107                                     // check & update map of what's occupied                             
3108                                     deleteOnInvalidPlacement.set(false);                                 
3109                                     if (!checkItemPlacement(occupied, appWidgetInfo,                     
3110                                             deleteOnInvalidPlacement)) {                                 
3111                                         if (deleteOnInvalidPlacement.get()) {                            
3112                                             itemsToRemove.add(id);                                       
3113                                         }                                                                
3114                                         break;                                                           
3115                                     }                                                                    
3116                                                                                                          
3117                                     String providerName = appWidgetInfo.providerName.flattenToString();  
3118                                     if (!providerName.equals(savedProvider) ||                           
3119                                             (appWidgetInfo.restoreStatus != restoreStatus)) {            
3120                                         ContentValues values = new ContentValues();                      
3121                                         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,        
3122                                                 providerName);                                           
3123                                         values.put(LauncherSettings.Favorites.RESTORED,                  
3124                                                 appWidgetInfo.restoreStatus);                            
3125                                         String where = BaseColumns._ID + "= ?";                          
3126                                         String[] args = {Long.toString(id)};                             
3127                                         contentResolver.update(contentUri, values, where, args);         
3128                                     }                                                                    
3129                                     sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);                  
3130                                     sBgAppWidgets.add(appWidgetInfo);                                    
3131                                 }                                                                        
3132                                 break;                                                                   
3133                             }                                                                            
3134                         } catch (Exception e) {                                                          
3135                             Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);      
3136                         }                                                                                
3137                     }                                                                                    
3138                 } finally {                                                                              
3139                     if (c != null) {                                                                     
3140                         c.close();                                                                       
3141                     }                                                                                    
3142                 }                                                                                        
3143                                                                                                          
3144                 // Break early if we've stopped loading                                                  
3145                 if (mStopped) {                                                                          
3146                     clearSBgDataStructures();                                                            
3147                     return false;                                                                        
3148                 }                                                                                        
3149                                                                                                          
3150                 if (itemsToRemove.size() > 0) {                                                          
3151                     ContentProviderClient client = contentResolver.acquireContentProviderClient(         
3152                             contentUri);                                                                 
3153                     // Remove dead items                                                                 
3154                     for (long id : itemsToRemove) {                                                      
3155                         if (DEBUG_LOADERS) {                                                             
3156                             Log.d(TAG, "Removed id = " + id);                                            
3157                         }                                                                                
3158                         // Don't notify content observers                                                
3159                         try {                                                                            
3160                             client.delete(LauncherSettings.Favorites.getContentUri(id, false),           
3161                                     null, null);                                                         
3162                         } catch (RemoteException e) {                                                    
3163                             Log.w(TAG, "Could not remove id = " + id);                                   
3164                         }                                                                                
3165                     }                                                                                    
3166                 }                                                                                        
3167                                                                                                          
3168                 if (restoredRows.size() > 0) {                                                           
3169                     ContentProviderClient updater = contentResolver.acquireContentProviderClient(        
3170                             contentUri);                                                                 
3171                     // Update restored items that no longer require special handling                     
3172                     try {                                                                                
3173                         StringBuilder selectionBuilder = new StringBuilder();                            
3174                         selectionBuilder.append(LauncherSettings.Favorites._ID);                         
3175                         selectionBuilder.append(" IN (");                                                
3176                         selectionBuilder.append(TextUtils.join(", ", restoredRows));                     
3177                         selectionBuilder.append(")");                                                    
3178                         ContentValues values = new ContentValues();                                      
3179                         values.put(LauncherSettings.Favorites.RESTORED, 0);                              
3180                         updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,           
3181                                 values, selectionBuilder.toString(), null);                              
3182                     } catch (RemoteException e) {                                                        
3183                         Log.w(TAG, "Could not update restored rows");                                    
3184                     }                                                                                    
3185                 }                                                                                        
3186                                                                                                          
3187                 if (!isSdCardReady && !sPendingPackages.isEmpty()) {                                     
3188                     context.registerReceiver(new AppsAvailabilityCheck(),                                
3189                             new IntentFilter(StartupReceiver.SYSTEM_READY),                              
3190                             null, sWorker);                                                              
3191                 }                                                                                        
3192                                                                                                          
3193                 if (loadedOldDb) {                                                                       
3194                     long maxScreenId = 0;                                                                
3195                     // If we're importing we use the old screen order.                                   
3196                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
3197                         long screenId = item.screenId;                                                   
3198                         if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&            
3199                                 !sBgWorkspaceScreens.contains(screenId)) {                               
3200                             sBgWorkspaceScreens.add(screenId);                                           
3201                             if (screenId > maxScreenId) {                                                
3202                                 maxScreenId = screenId;                                                  
3203                             }                                                                            
3204                         }                                                                                
3205                     }                                                                                    
3206                     Collections.sort(sBgWorkspaceScreens);                                               
3207                     // Log to disk                                                                       
3208                     Launcher.addDumpLog(TAG, "11683562 -   maxScreenId: " + maxScreenId, true);          
3209                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                      
3210                             TextUtils.join(", ", sBgWorkspaceScreens), true);                            
3211                                                                                                          
3212                     LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);               
3213                     updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                            
3214                                                                                                          
3215                     // Update the max item id after we load an old db                                    
3216                     long maxItemId = 0;                                                                  
3217                     // If we're importing we use the old screen order.                                   
3218                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
3219                         maxItemId = Math.max(maxItemId, item.id);                                        
3220                     }                                                                                    
3221                     LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);                   
3222                 } else {                                                                                 
3223                     TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(mContext);            
3224                     for (Integer i : orderedScreens.keySet()) {                                          
3225                         sBgWorkspaceScreens.add(orderedScreens.get(i));                                  
3226                     }                                                                                    
3227                     // Log to disk                                                                       
3228                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                      
3229                             TextUtils.join(", ", sBgWorkspaceScreens), true);                            
3230                                                                                                          
3231                     // Remove any empty screens                                                          
3232                     ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);            
3233                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
3234                         long screenId = item.screenId;                                                   
3235                         if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&            
3236                                 unusedScreens.contains(screenId)) {                                      
3237                             unusedScreens.remove(screenId);                                              
3238                         }                                                                                
3239                     }                                                                                    
3240                                                                                                          
3241                     // If there are any empty screens remove them, and update.                           
3242                     if (unusedScreens.size() != 0) {                                                     
3243                         // Log to disk                                                                   
3244                         Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " +        
3245                                 TextUtils.join(", ", unusedScreens), true);                              
3246                                                                                                          
3247                         sBgWorkspaceScreens.removeAll(unusedScreens);                                    
3248                         updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                        
3249                     }                                                                                    
3250                 }                                                                                        
3251                                                                                                          
3252                 if (DEBUG_LOADERS) {                                                                     
3253                     Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");          
3254                     Log.d(TAG, "workspace layout: ");                                                    
3255                     int nScreens = occupied.size();                                                      
3256                     for (int y = 0; y < countY; y++) {                                                   
3257                         String line = "";                                                                
3258                                                                                                          
3259                         Iterator<Long> iter = occupied.keySet().iterator();                              
3260                         while (iter.hasNext()) {                                                         
3261                             long screenId = iter.next();                                                 
3262                             if (screenId > 0) {                                                          
3263                                 line += " | ";                                                           
3264                             }                                                                            
3265                             for (int x = 0; x < countX; x++) {                                           
3266                                 ItemInfo[][] screen = occupied.get(screenId);                            
3267                                 if (x < screen.length && y < screen[x].length) {                         
3268                                     line += (screen[x][y] != null) ? "#" : ".";                          
3269                                 } else {                                                                 
3270                                     line += "!";                                                         
3271                                 }                                                                        
3272                             }                                                                            
3273                         }                                                                                
3274                         Log.d(TAG, "[ " + line + " ]");                                                  
3275                     }                                                                                    
3276                 }                                                                                        
3277             }                                                                                            
3278             return loadedOldDb;                                                                          
3279         }                                                                                                
3280                                                                                                          
3281         /** Filters the set of items who are directly or indirectly (via another container) on the       
3282          * specified screen. */                                                                          
3283         private void filterCurrentWorkspaceItems(long currentScreenId,                                   
3284                 ArrayList<ItemInfo> allWorkspaceItems,                                                   
3285                 ArrayList<ItemInfo> currentScreenItems,                                                  
3286                 ArrayList<ItemInfo> otherScreenItems) {                                                  
3287             // Purge any null ItemInfos                                                                  
3288             Iterator<ItemInfo> iter = allWorkspaceItems.iterator();                                      
3289             while (iter.hasNext()) {                                                                     
3290                 ItemInfo i = iter.next();                                                                
3291                 if (i == null) {                                                                         
3292                     iter.remove();                                                                       
3293                 }                                                                                        
3294             }                                                                                            
3295                                                                                                          
3296             // Order the set of items by their containers first, this allows use to walk through the     
3297             // list sequentially, build up a list of containers that are in the specified screen,        
3298             // as well as all items in those containers.                                                 
3299             Set<Long> itemsOnScreen = new HashSet<Long>();                                               
3300             Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {                             
3301                 @Override                                                                                
3302                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
3303                     return (int) (lhs.container - rhs.container);                                        
3304                 }                                                                                        
3305             });                                                                                          
3306             for (ItemInfo info : allWorkspaceItems) {                                                    
3307                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                    
3308                     if (info.screenId == currentScreenId) {                                              
3309                         currentScreenItems.add(info);                                                    
3310                         itemsOnScreen.add(info.id);                                                      
3311                     } else {                                                                             
3312                         otherScreenItems.add(info);                                                      
3313                     }                                                                                    
3314                 } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {             
3315                     currentScreenItems.add(info);                                                        
3316                     itemsOnScreen.add(info.id);                                                          
3317                 } else {                                                                                 
3318                     if (itemsOnScreen.contains(info.container)) {                                        
3319                         currentScreenItems.add(info);                                                    
3320                         itemsOnScreen.add(info.id);                                                      
3321                     } else {                                                                             
3322                         otherScreenItems.add(info);                                                      
3323                     }                                                                                    
3324                 }                                                                                        
3325             }                                                                                            
3326         }                                                                                                
3327                                                                                                          
3328         /** Filters the set of widgets which are on the specified screen. */                             
3329         private void filterCurrentAppWidgets(long currentScreenId,                                       
3330                 ArrayList<LauncherAppWidgetInfo> appWidgets,                                             
3331                 ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,                                   
3332                 ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {                                   
3333                                                                                                          
3334             for (LauncherAppWidgetInfo widget : appWidgets) {                                            
3335                 if (widget == null) continue;                                                            
3336                 if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                  
3337                         widget.screenId == currentScreenId) {                                            
3338                     currentScreenWidgets.add(widget);                                                    
3339                 } else {                                                                                 
3340                     otherScreenWidgets.add(widget);                                                      
3341                 }                                                                                        
3342             }                                                                                            
3343         }                                                                                                
3344                                                                                                          
3345         /** Filters the set of folders which are on the specified screen. */                             
3346         private void filterCurrentFolders(long currentScreenId,                                          
3347                 HashMap<Long, ItemInfo> itemsIdMap,                                                      
3348                 HashMap<Long, FolderInfo> folders,                                                       
3349                 HashMap<Long, FolderInfo> currentScreenFolders,                                          
3350                 HashMap<Long, FolderInfo> otherScreenFolders) {                                          
3351                                                                                                          
3352             for (long id : folders.keySet()) {                                                           
3353                 ItemInfo info = itemsIdMap.get(id);                                                      
3354                 FolderInfo folder = folders.get(id);                                                     
3355                 if (info == null || folder == null) continue;                                            
3356                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                    
3357                         info.screenId == currentScreenId) {                                              
3358                     currentScreenFolders.put(id, folder);                                                
3359                 } else {                                                                                 
3360                     otherScreenFolders.put(id, folder);                                                  
3361                 }                                                                                        
3362             }                                                                                            
3363         }                                                                                                
3364                                                                                                          
3365         /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to          
3366          * right) */                                                                                     
3367         private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {                   
3368             final LauncherAppState app = LauncherAppState.getInstance();                                 
3369             final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                          
3370             // XXX: review this                                                                          
3371             Collections.sort(workspaceItems, new Comparator<ItemInfo>() {                                
3372                 @Override                                                                                
3373                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
3374                     int cellCountX = (int) grid.numColumns;                                              
3375                     int cellCountY = (int) grid.numRows;                                                 
3376                     int screenOffset = cellCountX * cellCountY;                                          
3377                     int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat      
3378                     long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +           
3379                             lhs.cellY * cellCountX + lhs.cellX);                                         
3380                     long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +           
3381                             rhs.cellY * cellCountX + rhs.cellX);                                         
3382                     return (int) (lr - rr);                                                              
3383                 }                                                                                        
3384             });                                                                                          
3385         }                                                                                                
3386                                                                                                          
3387         private void bindWorkspaceScreens(final Callbacks oldCallbacks,                                  
3388                 final ArrayList<Long> orderedScreens) {                                                  
3389             final Runnable r = new Runnable() {                                                          
3390                 @Override                                                                                
3391                 public void run() {                                                                      
3392                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
3393                     if (callbacks != null) {                                                             
3394                         callbacks.bindScreens(orderedScreens);                                           
3395                     }                                                                                    
3396                 }                                                                                        
3397             };                                                                                           
3398             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
3399         }                                                                                                
3400                                                                                                          
3401         private void bindWorkspaceItems(final Callbacks oldCallbacks,                                    
3402                 final ArrayList<ItemInfo> workspaceItems,                                                
3403                 final ArrayList<LauncherAppWidgetInfo> appWidgets,                                       
3404                 final HashMap<Long, FolderInfo> folders,                                                 
3405                 ArrayList<Runnable> deferredBindRunnables) {                                             
3406                                                                                                          
3407             final boolean postOnMainThread = (deferredBindRunnables != null);                            
3408                                                                                                          
3409             // Bind the workspace items                                                                  
3410             int N = workspaceItems.size();                                                               
3411             for (int i = 0; i < N; i += ITEMS_CHUNK) {                                                   
3412                 final int start = i;                                                                     
3413                 final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);                        
3414                 final Runnable r = new Runnable() {                                                      
3415                     @Override                                                                            
3416                     public void run() {                                                                  
3417                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
3418                         if (callbacks != null) {                                                         
3419                             callbacks.bindItems(workspaceItems, start, start+chunkSize,                  
3420                                     false);                                                              
3421                         }                                                                                
3422                     }                                                                                    
3423                 };                                                                                       
3424                 if (postOnMainThread) {                                                                  
3425                     synchronized (deferredBindRunnables) {                                               
3426                         deferredBindRunnables.add(r);                                                    
3427                     }                                                                                    
3428                 } else {                                                                                 
3429                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
3430                 }                                                                                        
3431             }                                                                                            
3432                                                                                                          
3433             // Bind the folders                                                                          
3434             if (!folders.isEmpty()) {                                                                    
3435                 final Runnable r = new Runnable() {                                                      
3436                     public void run() {                                                                  
3437                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
3438                         if (callbacks != null) {                                                         
3439                             callbacks.bindFolders(folders);                                              
3440                         }                                                                                
3441                     }                                                                                    
3442                 };                                                                                       
3443                 if (postOnMainThread) {                                                                  
3444                     synchronized (deferredBindRunnables) {                                               
3445                         deferredBindRunnables.add(r);                                                    
3446                     }                                                                                    
3447                 } else {                                                                                 
3448                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
3449                 }                                                                                        
3450             }                                                                                            
3451                                                                                                          
3452             // Bind the widgets, one at a time                                                           
3453             N = appWidgets.size();                                                                       
3454             for (int i = 0; i < N; i++) {                                                                
3455                 final LauncherAppWidgetInfo widget = appWidgets.get(i);                                  
3456                 final Runnable r = new Runnable() {                                                      
3457                     public void run() {                                                                  
3458                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
3459                         if (callbacks != null) {                                                         
3460                             callbacks.bindAppWidget(widget);                                             
3461                         }                                                                                
3462                     }                                                                                    
3463                 };                                                                                       
3464                 if (postOnMainThread) {                                                                  
3465                     deferredBindRunnables.add(r);                                                        
3466                 } else {                                                                                 
3467                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
3468                 }                                                                                        
3469             }                                                                                            
3470         }                                                                                                
3471                                                                                                          
3472         /**                                                                                              
3473          * Binds all loaded data to actual views on the main thread.                                     
3474          */                                                                                              
3475         private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {               
3476             final long t = SystemClock.uptimeMillis();                                                   
3477             Runnable r;                                                                                  
3478                                                                                                          
3479             // Don't use these two variables in any of the callback runnables.                           
3480             // Otherwise we hold a reference to them.                                                    
3481             final Callbacks oldCallbacks = mCallbacks.get();                                             
3482             if (oldCallbacks == null) {                                                                  
3483                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
3484                 Log.w(TAG, "LoaderTask running with no launcher");                                       
3485                 return;                                                                                  
3486             }                                                                                            
3487                                                                                                          
3488             // Save a copy of all the bg-thread collections                                              
3489             ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();                              
3490             ArrayList<LauncherAppWidgetInfo> appWidgets =                                                
3491                     new ArrayList<LauncherAppWidgetInfo>();                                              
3492             HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();                         
3493             HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();                          
3494             ArrayList<Long> orderedScreenIds = new ArrayList<Long>();                                    
3495             synchronized (sBgLock) {                                                                     
3496                 workspaceItems.addAll(sBgWorkspaceItems);                                                
3497                 appWidgets.addAll(sBgAppWidgets);                                                        
3498                 folders.putAll(sBgFolders);                                                              
3499                 itemsIdMap.putAll(sBgItemsIdMap);                                                        
3500                 orderedScreenIds.addAll(sBgWorkspaceScreens);                                            
3501             }                                                                                            
3502                                                                                                          
3503             final boolean isLoadingSynchronously =                                                       
3504                     synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;                               
3505             int currScreen = isLoadingSynchronously ? synchronizeBindPage :                              
3506                 oldCallbacks.getCurrentWorkspaceScreen();                                                
3507             if (currScreen >= orderedScreenIds.size()) {                                                 
3508                 // There may be no workspace screens (just hotseat items and an empty page).             
3509                 currScreen = PagedView.INVALID_RESTORE_PAGE;                                             
3510             }                                                                                            
3511             final int currentScreen = currScreen;                                                        
3512             final long currentScreenId = currentScreen < 0                                               
3513                     ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);                           
3514                                                                                                          
3515             // Load all the items that are on the current page first (and in the process, unbind         
3516             // all the existing workspace items before we call startBinding() below.                     
3517             unbindWorkspaceItemsOnMainThread();                                                          
3518                                                                                                          
3519             // Separate the items that are on the current screen, and all the other remaining items      
3520             ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();                       
3521             ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();                         
3522             ArrayList<LauncherAppWidgetInfo> currentAppWidgets =                                         
3523                     new ArrayList<LauncherAppWidgetInfo>();                                              
3524             ArrayList<LauncherAppWidgetInfo> otherAppWidgets =                                           
3525                     new ArrayList<LauncherAppWidgetInfo>();                                              
3526             HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();                  
3527             HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();                    
3528                                                                                                          
3529             filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,          
3530                     otherWorkspaceItems);                                                                
3531             filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,                      
3532                     otherAppWidgets);                                                                    
3533             filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,                   
3534                     otherFolders);                                                                       
3535             sortWorkspaceItemsSpatially(currentWorkspaceItems);                                          
3536             sortWorkspaceItemsSpatially(otherWorkspaceItems);                                            
3537                                                                                                          
3538             // Tell the workspace that we're about to start binding items                                
3539             r = new Runnable() {                                                                         
3540                 public void run() {                                                                      
3541                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
3542                     if (callbacks != null) {                                                             
3543                         callbacks.startBinding();                                                        
3544                     }                                                                                    
3545                 }                                                                                        
3546             };                                                                                           
3547             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
3548                                                                                                          
3549             bindWorkspaceScreens(oldCallbacks, orderedScreenIds);                                        
3550                                                                                                          
3551             // Load items on the current page                                                            
3552             bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,                   
3553                     currentFolders, null);                                                               
3554             if (isLoadingSynchronously) {                                                                
3555                 r = new Runnable() {                                                                     
3556                     public void run() {                                                                  
3557                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
3558                         if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {      
3559                             callbacks.onPageBoundSynchronously(currentScreen);                           
3560                         }                                                                                
3561                     }                                                                                    
3562                 };                                                                                       
3563                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
3564             }                                                                                            
3565                                                                                                          
3566             // Load all the remaining pages (if we are loading synchronously, we want to defer this      
3567             // work until after the first render)                                                        
3568             synchronized (mDeferredBindRunnables) {                                                      
3569                 mDeferredBindRunnables.clear();                                                          
3570             }                                                                                            
3571             bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,         
3572                     (isLoadingSynchronously ? mDeferredBindRunnables : null));                           
3573                                                                                                          
3574             // Tell the workspace that we're done binding items                                          
3575             r = new Runnable() {                                                                         
3576                 public void run() {                                                                      
3577                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
3578                     if (callbacks != null) {                                                             
3579                         callbacks.finishBindingItems(isUpgradePath);                                     
3580                     }                                                                                    
3581                                                                                                          
3582                     // If we're profiling, ensure this is the last thing in the queue.                   
3583                     if (DEBUG_LOADERS) {                                                                 
3584                         Log.d(TAG, "bound workspace in "                                                 
3585                             + (SystemClock.uptimeMillis()-t) + "ms");                                    
3586                     }                                                                                    
3587                                                                                                          
3588                     mIsLoadingAndBindingWorkspace = false;                                               
3589                 }                                                                                        
3590             };                                                                                           
3591             if (isLoadingSynchronously) {                                                                
3592                 synchronized (mDeferredBindRunnables) {                                                  
3593                     mDeferredBindRunnables.add(r);                                                       
3594                 }                                                                                        
3595             } else {                                                                                     
3596                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
3597             }                                                                                            
3598         }                                                                                                
3599                                                                                                          
3600         private void loadAndBindAllApps() {                                                              
3601             if (DEBUG_LOADERS) {                                                                         
3602                 Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);                       
3603             }                                                                                            
3604             if (!mAllAppsLoaded) {                                                                       
3605                 loadAllApps();                                                                           
3606                 synchronized (LoaderTask.this) {                                                         
3607                     if (mStopped) {                                                                      
3608                         return;                                                                          
3609                     }                                                                                    
3610                     mAllAppsLoaded = true;                                                               
3611                 }                                                                                        
3612             } else {                                                                                     
3613                 onlyBindAllApps();                                                                       
3614             }                                                                                            
3615         }                                                                                                
3616                                                                                                          
3617         private void onlyBindAllApps() {                                                                 
3618             final Callbacks oldCallbacks = mCallbacks.get();                                             
3619             if (oldCallbacks == null) {                                                                  
3620                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
3621                 Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");                     
3622                 return;                                                                                  
3623             }                                                                                            
3624                                                                                                          
3625             // shallow copy                                                                              
3626             @SuppressWarnings("unchecked")                                                               
3627             final ArrayList<AppInfo> list                                                                
3628                     = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();                                  
3629             Runnable r = new Runnable() {                                                                
3630                 public void run() {                                                                      
3631                     final long t = SystemClock.uptimeMillis();                                           
3632                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
3633                     if (callbacks != null) {                                                             
3634                         callbacks.bindAllApplications(list);                                             
3635                     }                                                                                    
3636                     if (DEBUG_LOADERS) {                                                                 
3637                         Log.d(TAG, "bound all " + list.size() + " apps from cache in "                   
3638                                 + (SystemClock.uptimeMillis()-t) + "ms");                                
3639                     }                                                                                    
3640                 }                                                                                        
3641             };                                                                                           
3642             boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());           
3643             if (isRunningOnMainThread) {                                                                 
3644                 r.run();                                                                                 
3645             } else {                                                                                     
3646                 mHandler.post(r);                                                                        
3647             }                                                                                            
3648         }                                                                                                
3649                                                                                                          
3650         private void loadAllApps() {                                                                     
3651             final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                        
3652                                                                                                          
3653             final Callbacks oldCallbacks = mCallbacks.get();                                             
3654             if (oldCallbacks == null) {                                                                  
3655                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
3656                 Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");                         
3657                 return;                                                                                  
3658             }                                                                                            
3659                                                                                                          
3660             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);                              
3661             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                            
3662                                                                                                          
3663             final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();                      
3664                                                                                                          
3665             // Clear the list of apps                                                                    
3666             mBgAllAppsList.clear();                                                                      
3667             for (UserHandleCompat user : profiles) {                                                     
3668                 // Query for the set of apps                                                             
3669                 final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                     
3670                 List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);       
3671                 if (DEBUG_LOADERS) {                                                                     
3672                     Log.d(TAG, "getActivityList took "                                                   
3673                             + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);             
3674                     Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);         
3675                 }                                                                                        
3676                 // Fail if we don't have any apps                                                        
3677                 if (apps == null || apps.isEmpty()) {                                                    
3678                     return;                                                                              
3679                 }                                                                                        
3680                 // Sort the applications by name                                                         
3681                 final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                    
3682                 Collections.sort(apps,                                                                   
3683                         new LauncherModel.ShortcutNameComparator(mLabelCache));                          
3684                 if (DEBUG_LOADERS) {                                                                     
3685                     Log.d(TAG, "sort took "                                                              
3686                             + (SystemClock.uptimeMillis()-sortTime) + "ms");                             
3687                 }                                                                                        
3688                                                                                                          
3689                 // Create the ApplicationInfos                                                           
3690                 for (int i = 0; i < apps.size(); i++) {                                                  
3691                     LauncherActivityInfoCompat app = apps.get(i);                                        
3692                     // This builds the icon bitmaps.                                                     
3693                     mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));       
3694                 }                                                                                        
3695             }                                                                                            
3696             // Huh? Shouldn't this be inside the Runnable below?                                         
3697             final ArrayList<AppInfo> added = mBgAllAppsList.added;                                       
3698             mBgAllAppsList.added = new ArrayList<AppInfo>();                                             
3699                                                                                                          
3700             // Post callback on main thread                                                              
3701             mHandler.post(new Runnable() {                                                               
3702                 public void run() {                                                                      
3703                     final long bindTime = SystemClock.uptimeMillis();                                    
3704                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
3705                     if (callbacks != null) {                                                             
3706                         callbacks.bindAllApplications(added);                                            
3707                         if (DEBUG_LOADERS) {                                                             
3708                             Log.d(TAG, "bound " + added.size() + " apps in "                             
3709                                 + (SystemClock.uptimeMillis() - bindTime) + "ms");                       
3710                         }                                                                                
3711                     } else {                                                                             
3712                         Log.i(TAG, "not binding apps: no Launcher activity");                            
3713                     }                                                                                    
3714                 }                                                                                        
3715             });                                                                                          
3716                                                                                                          
3717             if (DEBUG_LOADERS) {                                                                         
3718                 Log.d(TAG, "Icons processed in "                                                         
3719                         + (SystemClock.uptimeMillis() - loadTime) + "ms");                               
3720             }                                                                                            
3721         }                                                                                                
3722                                                                                                          
3723         public void dumpState() {                                                                        
3724             synchronized (sBgLock) {                                                                     
3725                 Log.d(TAG, "mLoaderTask.mContext=" + mContext);                                          
3726                 Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);                                  
3727                 Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);                                          
3728                 Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);          
3729                 Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());                                   
3730             }                                                                                            
3731         }                                                                                                
3732     }                                                                                                    
3733                                                                                                          
3734     void enqueuePackageUpdated(PackageUpdatedTask task) {                                                
3735         sWorker.post(task);                                                                              
3736     }                                                                                                    
3737                                                                                                          
3738     private class AppsAvailabilityCheck extends BroadcastReceiver {                                      
3739                                                                                                          
3740         @Override                                                                                        
3741         public void onReceive(Context context, Intent intent) {                                          
3742             synchronized (sBgLock) {                                                                     
3743                 final LauncherAppsCompat launcherApps = LauncherAppsCompat                               
3744                         .getInstance(mApp.getContext());                                                 
3745                 ArrayList<String> packagesRemoved;                                                       
3746                 for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {     
3747                     UserHandleCompat user = entry.getKey();                                              
3748                     packagesRemoved = new ArrayList<String>();                                           
3749                     for (String pkg : entry.getValue()) {                                                
3750                         if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {                       
3751                             Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);                 
3752                             packagesRemoved.add(pkg);                                                    
3753                         }                                                                                
3754                     }                                                                                    
3755                     if (!packagesRemoved.isEmpty()) {                                                    
3756                         enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,       
3757                                 packagesRemoved.toArray(new String[packagesRemoved.size()]), user));     
3758                     }                                                                                    
3759                 }                                                                                        
3760                 sPendingPackages.clear();                                                                
3761             }                                                                                            
3762         }                                                                                                
3763     }                                                                                                    
3764                                                                                                          
3765     /**                                                                                                  
3766      * Workaround to re-check unrestored items, in-case they were installed but the Package-ADD          
3767      * runnable was missed by the launcher.                                                              
3768      */                                                                                                  
3769     public void recheckRestoredItems(final Context context) {                                            
3770         Runnable r = new Runnable() {                                                                    
3771                                                                                                          
3772             @Override                                                                                    
3773             public void run() {                                                                          
3774                 LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);               
3775                 HashSet<String> installedPackages = new HashSet<String>();                               
3776                 UserHandleCompat user = UserHandleCompat.myUserHandle();                                 
3777                 synchronized(sBgLock) {                                                                  
3778                     for (ItemInfo info : sBgItemsIdMap.values()) {                                       
3779                         if (info instanceof ShortcutInfo) {                                              
3780                             ShortcutInfo si = (ShortcutInfo) info;                                       
3781                             if (si.isPromise() && si.getTargetComponent() != null                        
3782                                     && launcherApps.isPackageEnabledForProfile(                          
3783                                             si.getTargetComponent().getPackageName(), user)) {           
3784                                 installedPackages.add(si.getTargetComponent().getPackageName());         
3785                             }                                                                            
3786                         } else if (info instanceof LauncherAppWidgetInfo) {                              
3787                             LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) info;                 
3788                             if (widget.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)     
3789                                     && launcherApps.isPackageEnabledForProfile(                          
3790                                             widget.providerName.getPackageName(), user)) {               
3791                                 installedPackages.add(widget.providerName.getPackageName());             
3792                             }                                                                            
3793                         }                                                                                
3794                     }                                                                                    
3795                 }                                                                                        
3796                                                                                                          
3797                 if (!installedPackages.isEmpty()) {                                                      
3798                     final ArrayList<AppInfo> restoredApps = new ArrayList<AppInfo>();                    
3799                     for (String pkg : installedPackages) {                                               
3800                         for (LauncherActivityInfoCompat info : launcherApps.getActivityList(pkg, user)) {
3801                             restoredApps.add(new AppInfo(context, info, user, mIconCache, null));        
3802                         }                                                                                
3803                     }                                                                                    
3804                                                                                                          
3805                     final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;            
3806                     if (!restoredApps.isEmpty()) {                                                       
3807                         mHandler.post(new Runnable() {                                                   
3808                             public void run() {                                                          
3809                                 Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;             
3810                                 if (callbacks == cb && cb != null) {                                     
3811                                     callbacks.bindAppsRestored(restoredApps);                            
3812                                 }                                                                        
3813                             }                                                                            
3814                         });                                                                              
3815                     }                                                                                    
3816                                                                                                          
3817                 }                                                                                        
3818             }                                                                                            
3819         };                                                                                               
3820         sWorker.post(r);                                                                                 
3821     }                                                                                                    
3822                                                                                                          
3823     private class PackageUpdatedTask implements Runnable {                                               
3824         int mOp;                                                                                         
3825         String[] mPackages;                                                                              
3826         UserHandleCompat mUser;                                                                          
3827                                                                                                          
3828         public static final int OP_NONE = 0;                                                             
3829         public static final int OP_ADD = 1;                                                              
3830         public static final int OP_UPDATE = 2;                                                           
3831         public static final int OP_REMOVE = 3; // uninstlled                                             
3832         public static final int OP_UNAVAILABLE = 4; // external media unmounted                          
3833                                                                                                          
3834                                                                                                          
3835         public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {                    
3836             mOp = op;                                                                                    
3837             mPackages = packages;                                                                        
3838             mUser = user;                                                                                
3839         }                                                                                                
3840                                                                                                          
3841         public void run() {                                                                              
3842             final Context context = mApp.getContext();                                                   
3843                                                                                                          
3844             final String[] packages = mPackages;                                                         
3845             final int N = packages.length;                                                               
3846             switch (mOp) {                                                                               
3847                 case OP_ADD:                                                                             
3848                     for (int i=0; i<N; i++) {                                                            
3849                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);         
3850                         mIconCache.remove(packages[i], mUser);                                           
3851                         mBgAllAppsList.addPackage(context, packages[i], mUser);                          
3852                     }                                                                                    
3853                     break;                                                                               
3854                 case OP_UPDATE:                                                                          
3855                     for (int i=0; i<N; i++) {                                                            
3856                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);      
3857                         mBgAllAppsList.updatePackage(context, packages[i], mUser);                       
3858                         WidgetPreviewLoader.removePackageFromDb(                                         
3859                                 mApp.getWidgetPreviewCacheDb(), packages[i]);                            
3860                     }                                                                                    
3861                     break;                                                                               
3862                 case OP_REMOVE:                                                                          
3863                 case OP_UNAVAILABLE:                                                                     
3864                     for (int i=0; i<N; i++) {                                                            
3865                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);      
3866                         mBgAllAppsList.removePackage(packages[i], mUser);                                
3867                         WidgetPreviewLoader.removePackageFromDb(                                         
3868                                 mApp.getWidgetPreviewCacheDb(), packages[i]);                            
3869                     }                                                                                    
3870                     break;                                                                               
3871             }                                                                                            
3872                                                                                                          
3873             ArrayList<AppInfo> added = null;                                                             
3874             ArrayList<AppInfo> modified = null;                                                          
3875             final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();                             
3876                                                                                                          
3877             if (mBgAllAppsList.added.size() > 0) {                                                       
3878                 added = new ArrayList<AppInfo>(mBgAllAppsList.added);                                    
3879                 mBgAllAppsList.added.clear();                                                            
3880             }                                                                                            
3881             if (mBgAllAppsList.modified.size() > 0) {                                                    
3882                 modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);                              
3883                 mBgAllAppsList.modified.clear();                                                         
3884             }                                                                                            
3885             if (mBgAllAppsList.removed.size() > 0) {                                                     
3886                 removedApps.addAll(mBgAllAppsList.removed);                                              
3887                 mBgAllAppsList.removed.clear();                                                          
3888             }                                                                                            
3889                                                                                                          
3890             final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                    
3891             if (callbacks == null) {                                                                     
3892                 Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");          
3893                 return;                                                                                  
3894             }                                                                                            
3895                                                                                                          
3896             if (added != null) {                                                                         
3897                 // Ensure that we add all the workspace applications to the db                           
3898                 if (LauncherAppState.isDisableAllApps()) {                                               
3899                     final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);               
3900                     addAndBindAddedWorkspaceApps(context, addedInfos);                                   
3901                 } else {                                                                                 
3902                     addAppsToAllApps(context, added);                                                    
3903                 }                                                                                        
3904             }                                                                                            
3905                                                                                                          
3906             if (modified != null) {                                                                      
3907                 final ArrayList<AppInfo> modifiedFinal = modified;                                       
3908                                                                                                          
3909                 // Update the launcher db to reflect the changes                                         
3910                 for (AppInfo a : modifiedFinal) {                                                        
3911                     ArrayList<ItemInfo> infos =                                                          
3912                             getItemInfoForComponentName(a.componentName, mUser);                         
3913                     for (ItemInfo i : infos) {                                                           
3914                         if (isShortcutInfoUpdateable(i)) {                                               
3915                             ShortcutInfo info = (ShortcutInfo) i;                                        
3916                             info.title = a.title.toString();                                             
3917                             info.contentDescription = a.contentDescription;                              
3918                             updateItemInDatabase(context, info);                                         
3919                         }                                                                                
3920                     }                                                                                    
3921                 }                                                                                        
3922                                                                                                          
3923                 mHandler.post(new Runnable() {                                                           
3924                     public void run() {                                                                  
3925                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
3926                         if (callbacks == cb && cb != null) {                                             
3927                             callbacks.bindAppsUpdated(modifiedFinal);                                    
3928                         }                                                                                
3929                     }                                                                                    
3930                 });                                                                                      
3931             }                                                                                            
3932                                                                                                          
3933             final ArrayList<String> removedPackageNames =                                                
3934                     new ArrayList<String>();                                                             
3935             if (mOp == OP_REMOVE) {                                                                      
3936                 // Mark all packages in the broadcast to be removed                                      
3937                 removedPackageNames.addAll(Arrays.asList(packages));                                     
3938             } else if (mOp == OP_UPDATE) {                                                               
3939                 // Mark disabled packages in the broadcast to be removed                                 
3940                 final PackageManager pm = context.getPackageManager();                                   
3941                 for (int i=0; i<N; i++) {                                                                
3942                     if (isPackageDisabled(context, packages[i], mUser)) {                                
3943                         removedPackageNames.add(packages[i]);                                            
3944                     }                                                                                    
3945                 }                                                                                        
3946             }                                                                                            
3947             // Remove all the components associated with this package                                    
3948             for (String pn : removedPackageNames) {                                                      
3949                 deletePackageFromDatabase(context, pn, mUser);                                           
3950             }                                                                                            
3951             // Remove all the specific components                                                        
3952             for (AppInfo a : removedApps) {                                                              
3953                 ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);         
3954                 deleteItemsFromDatabase(context, infos);                                                 
3955             }                                                                                            
3956             if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {                              
3957                 // Remove any queued items from the install queue                                        
3958                 String spKey = LauncherAppState.getSharedPreferencesKey();                               
3959                 SharedPreferences sp =                                                                   
3960                         context.getSharedPreferences(spKey, Context.MODE_PRIVATE);                       
3961                 InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);                 
3962                 // Call the components-removed callback                                                  
3963                 mHandler.post(new Runnable() {                                                           
3964                     public void run() {                                                                  
3965                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
3966                         if (callbacks == cb && cb != null) {                                             
3967                             callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);    
3968                         }                                                                                
3969                     }                                                                                    
3970                 });                                                                                      
3971             }                                                                                            
3972                                                                                                          
3973             final ArrayList<Object> widgetsAndShortcuts =                                                
3974                     getSortedWidgetsAndShortcuts(context);                                               
3975             mHandler.post(new Runnable() {                                                               
3976                 @Override                                                                                
3977                 public void run() {                                                                      
3978                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
3979                     if (callbacks == cb && cb != null) {                                                 
3980                         callbacks.bindPackagesUpdated(widgetsAndShortcuts);                              
3981                     }                                                                                    
3982                 }                                                                                        
3983             });                                                                                          
3984                                                                                                          
3985             // Write all the logs to disk                                                                
3986             mHandler.post(new Runnable() {                                                               
3987                 public void run() {                                                                      
3988                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
3989                     if (callbacks == cb && cb != null) {                                                 
3990                         callbacks.dumpLogsToLocalData();                                                 
3991                     }                                                                                    
3992                 }                                                                                        
3993             });                                                                                          
3994         }                                                                                                
3995     }                                                                                                    
3996                                                                                                          
3997     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
3998     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
3999         PackageManager packageManager = context.getPackageManager();                                     
4000         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
4001         widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());       
4002                                                                                                          
4003         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
4004         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
4005         Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));             
4006         return widgetsAndShortcuts;                                                                      
4007     }                                                                                                    
4008                                                                                                          
4009     private static boolean isPackageDisabled(Context context, String packageName,                        
4010             UserHandleCompat user) {                                                                     
4011         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
4012         return !launcherApps.isPackageEnabledForProfile(packageName, user);                              
4013     }                                                                                                    
4014                                                                                                          
4015     public static boolean isValidPackageActivity(Context context, ComponentName cn,                      
4016             UserHandleCompat user) {                                                                     
4017         if (cn == null) {                                                                                
4018             return false;                                                                                
4019         }                                                                                                
4020         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
4021         if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {                       
4022             return false;                                                                                
4023         }                                                                                                
4024         return launcherApps.isActivityEnabledForProfile(cn, user);                                       
4025     }                                                                                                    
4026                                                                                                          
4027     public static boolean isValidPackage(Context context, String packageName,                            
4028             UserHandleCompat user) {                                                                     
4029         if (packageName == null) {                                                                       
4030             return false;                                                                                
4031         }                                                                                                
4032         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
4033         return launcherApps.isPackageEnabledForProfile(packageName, user);                               
4034     }                                                                                                    
4035                                                                                                          
4036     /**                                                                                                  
4037      * Make an ShortcutInfo object for a restored application or shortcut item that points               
4038      * to a package that is not yet installed on the system.                                             
4039      */                                                                                                  
4040 <<<<<<< GitAnalyzerPlus_ours                                                                             
4041     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,                
4042             int promiseType) {                                                                           
4043 ||||||| GitAnalyzerPlus_base                                                                             
4044                     public void run() {                                                                  
4045                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
4046                         if (callbacks == cb && cb != null) {                                             
4047                             callbacks.bindComponentsRemoved(removedPackageNames, removedApps);           
4048                         }                                                                                
4049                     }                                                                                    
4050                 });                                                                                      
4051             }                                                                                            
4052                                                                                                          
4053             final ArrayList<Object> widgetsAndShortcuts =                                                
4054                 getSortedWidgetsAndShortcuts(context);                                                   
4055             mHandler.post(new Runnable() {                                                               
4056                 @Override                                                                                
4057                 public void run() {                                                                      
4058                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
4059                     if (callbacks == cb && cb != null) {                                                 
4060                         callbacks.bindPackagesUpdated(widgetsAndShortcuts);                              
4061                     }                                                                                    
4062                 }                                                                                        
4063             });                                                                                          
4064                                                                                                          
4065             // Write all the logs to disk                                                                
4066             mHandler.post(new Runnable() {                                                               
4067                 public void run() {                                                                      
4068                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
4069                     if (callbacks == cb && cb != null) {                                                 
4070                         callbacks.dumpLogsToLocalData();                                                 
4071                     }                                                                                    
4072                 }                                                                                        
4073             });                                                                                          
4074         }                                                                                                
4075     }                                                                                                    
4076                                                                                                          
4077     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
4078     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
4079         PackageManager packageManager = context.getPackageManager();                                     
4080         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
4081         widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());       
4082         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
4083         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
4084         Collections.sort(widgetsAndShortcuts,                                                            
4085             new LauncherModel.WidgetAndShortcutNameComparator(packageManager));                          
4086         return widgetsAndShortcuts;                                                                      
4087     }                                                                                                    
4088                                                                                                          
4089     private static boolean isPackageDisabled(PackageManager pm, String packageName) {                    
4090         try {                                                                                            
4091             PackageInfo pi = pm.getPackageInfo(packageName, 0);                                          
4092             return !pi.applicationInfo.enabled;                                                          
4093         } catch (NameNotFoundException e) {                                                              
4094             // Fall through                                                                              
4095         }                                                                                                
4096         return false;                                                                                    
4097     }                                                                                                    
4098                                                                                                          
4099     public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {                 
4100         if (cn == null) {                                                                                
4101             return false;                                                                                
4102         }                                                                                                
4103         if (isPackageDisabled(pm, cn.getPackageName())) {                                                
4104             return false;                                                                                
4105         }                                                                                                
4106                                                                                                          
4107         try {                                                                                            
4108             // Check the activity                                                                        
4109             PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);                                  
4110             return (pm.getActivityInfo(cn, 0) != null);                                                  
4111         } catch (NameNotFoundException e) {                                                              
4112             return false;                                                                                
4113         }                                                                                                
4114     }                                                                                                    
4115                                                                                                          
4116     /**                                                                                                  
4117      * Make an ShortcutInfo object for a restored application or shortcut item that points               
4118      * to a package that is not yet installed on the system.                                             
4119      */                                                                                                  
4120     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {              
4121         final ShortcutInfo info = new ShortcutInfo();                                                    
4122         info.usingFallbackIcon = true;                                                                   
4123         info.setIcon(getFallbackIcon());                                                                 
4124         if (cursor != null) {                                                                            
4125             info.title =  cursor.getString(titleIndex);                                                  
4126         } else {                                                                                         
4127             info.title = "";                                                                             
4128         }                                                                                                
4129         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
4130         info.restoredIntent = intent;                                                                    
4131         return info;                                                                                     
4132     }                                                                                                    
4133                                                                                                          
4134     /**                                                                                                  
4135      * Make an Intent object for a restored application or shortcut item that points                     
4136      * to the market page for the item.                                                                  
4137      */                                                                                                  
4138     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
4139         final boolean debug = false;                                                                     
4140         ComponentName componentName = intent.getComponent();                                             
4141         Intent marketIntent = new Intent(Intent.ACTION_VIEW);                                            
4142         Uri marketUri = new Uri.Builder()                                                                
4143                 .scheme("market")                                                                        
4144                 .authority("details")                                                                    
4145                 .appendQueryParameter("id", componentName.getPackageName())                              
4146                 .build();                                                                                
4147         if (debug) Log.d(TAG, "manufactured intent uri: " + marketUri.toString());                       
4148         marketIntent.setData(marketUri);                                                                 
4149         return marketIntent;                                                                             
4150     }                                                                                                    
4151                                                                                                          
4152     /**                                                                                                  
4153      * This is called from the code that adds shortcuts from the intent receiver.  This                  
4154      * doesn't have a Cursor, but                                                                        
4155      */                                                                                                  
4156     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {        
4157         return getShortcutInfo(manager, intent, context, null, -1, -1, null);                            
4158     }                                                                                                    
4159                                                                                                          
4160     /**                                                                                                  
4161      * Make an ShortcutInfo object for a shortcut that is an application.                                
4162      *                                                                                                   
4163      * If c is not null, then it will be used to fill in missing data like the title and icon.           
4164      */                                                                                                  
4165     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,          
4166             Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {         
4167         ComponentName componentName = intent.getComponent();                                             
4168         final ShortcutInfo info = new ShortcutInfo();                                                    
4169         if (componentName != null && !isValidPackageComponent(manager, componentName)) {                 
4170             Log.d(TAG, "Invalid package found in getShortcutInfo: " + componentName);                    
4171             return null;                                                                                 
4172         } else {                                                                                         
4173             try {                                                                                        
4174                 PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);              
4175                 info.initFlagsAndFirstInstallTime(pi);                                                   
4176             } catch (NameNotFoundException e) {                                                          
4177                 Log.d(TAG, "getPackInfo failed for package " +                                           
4178                         componentName.getPackageName());                                                 
4179             }                                                                                            
4180         }                                                                                                
4181                                                                                                          
4182         // TODO: See if the PackageManager knows about this case.  If it doesn't                         
4183         // then return null & delete this.                                                               
4184                                                                                                          
4185         // the resource -- This may implicitly give us back the fallback icon,                           
4186         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
4187         // to avoid saving lots of copies of that in the database, and most apps                         
4188         // have icons anyway.                                                                            
4189                                                                                                          
4190         // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and      
4191         // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info     
4192         // via resolveActivity().                                                                        
4193         Bitmap icon = null;                                                                              
4194         ResolveInfo resolveInfo = null;                                                                  
4195         ComponentName oldComponent = intent.getComponent();                                              
4196         Intent newIntent = new Intent(intent.getAction(), null);                                         
4197         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
4198         newIntent.setPackage(oldComponent.getPackageName());                                             
4199         List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);                           
4200         for (ResolveInfo i : infos) {                                                                    
4201             ComponentName cn = new ComponentName(i.activityInfo.packageName,                             
4202                     i.activityInfo.name);                                                                
4203             if (cn.equals(oldComponent)) {                                                               
4204                 resolveInfo = i;                                                                         
4205             }                                                                                            
4206         }                                                                                                
4207         if (resolveInfo == null) {                                                                       
4208             resolveInfo = manager.resolveActivity(intent, 0);                                            
4209         }                                                                                                
4210         if (resolveInfo != null) {                                                                       
4211             icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);                           
4212         }                                                                                                
4213         // the db                                                                                        
4214         if (icon == null) {                                                                              
4215             if (c != null) {                                                                             
4216                 icon = getIconFromCursor(c, iconIndex, context);                                         
4217             }                                                                                            
4218         }                                                                                                
4219         // the fallback icon                                                                             
4220         if (icon == null) {                                                                              
4221             icon = getFallbackIcon();                                                                    
4222             info.usingFallbackIcon = true;                                                               
4223         }                                                                                                
4224         info.setIcon(icon);                                                                              
4225                                                                                                          
4226         // from the resource                                                                             
4227         if (resolveInfo != null) {                                                                       
4228             ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);              
4229             if (labelCache != null && labelCache.containsKey(key)) {                                     
4230                 info.title = labelCache.get(key);                                                        
4231             } else {                                                                                     
4232                 info.title = resolveInfo.activityInfo.loadLabel(manager);                                
4233                 if (labelCache != null) {                                                                
4234                     labelCache.put(key, info.title);                                                     
4235                 }                                                                                        
4236             }                                                                                            
4237         }                                                                                                
4238         // from the db                                                                                   
4239         if (info.title == null) {                                                                        
4240             if (c != null) {                                                                             
4241                 info.title =  c.getString(titleIndex);                                                   
4242             }                                                                                            
4243         }                                                                                                
4244         // fall back to the class name of the activity                                                   
4245         if (info.title == null) {                                                                        
4246             info.title = componentName.getClassName();                                                   
4247         }                                                                                                
4248         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
4249         return info;                                                                                     
4250     }                                                                                                    
4251                                                                                                          
4252     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
4253             ItemInfoFilter f) {                                                                          
4254         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
4255         for (ItemInfo i : infos) {                                                                       
4256             if (i instanceof ShortcutInfo) {                                                             
4257                 ShortcutInfo info = (ShortcutInfo) i;                                                    
4258                 ComponentName cn = info.intent.getComponent();                                           
4259                 if (cn != null && f.filterItem(null, info, cn)) {                                        
4260                     filtered.add(info);                                                                  
4261                 }                                                                                        
4262             } else if (i instanceof FolderInfo) {                                                        
4263                 FolderInfo info = (FolderInfo) i;                                                        
4264                 for (ShortcutInfo s : info.contents) {                                                   
4265                     ComponentName cn = s.intent.getComponent();                                          
4266                     if (cn != null && f.filterItem(info, s, cn)) {                                       
4267                         filtered.add(s);                                                                 
4268                     }                                                                                    
4269                 }                                                                                        
4270             } else if (i instanceof LauncherAppWidgetInfo) {                                             
4271                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
4272                 ComponentName cn = info.providerName;                                                    
4273                 if (cn != null && f.filterItem(null, info, cn)) {                                        
4274                     filtered.add(info);                                                                  
4275                 }                                                                                        
4276             }                                                                                            
4277         }                                                                                                
4278         return new ArrayList<ItemInfo>(filtered);                                                        
4279     }                                                                                                    
4280                                                                                                          
4281     private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {                             
4282         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
4283             @Override                                                                                    
4284             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
4285                 return cn.getPackageName().equals(pn);                                                   
4286             }                                                                                            
4287         };                                                                                               
4288         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
4289     }                                                                                                    
4290                                                                                                          
4291     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {                 
4292         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
4293             @Override                                                                                    
4294             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
4295                 return cn.equals(cname);                                                                 
4296             }                                                                                            
4297         };                                                                                               
4298         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
4299     }                                                                                                    
4300                                                                                                          
4301     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
4302         if (i instanceof ShortcutInfo) {                                                                 
4303             ShortcutInfo info = (ShortcutInfo) i;                                                        
4304             // We need to check for ACTION_MAIN otherwise getComponent() might                           
4305             // return null for some shortcuts (for instance, for shortcuts to                            
4306             // web pages.)                                                                               
4307             Intent intent = info.intent;                                                                 
4308             ComponentName name = intent.getComponent();                                                  
4309             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
4310                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
4311                 return true;                                                                             
4312             }                                                                                            
4313             // placeholder shortcuts get special treatment, let them through too.                        
4314             if (info.getRestoredIntent() != null) {                                                      
4315                 return true;                                                                             
4316             }                                                                                            
4317         }                                                                                                
4318         return false;                                                                                    
4319     }                                                                                                    
4320                                                                                                          
4321     /**                                                                                                  
4322      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
4323      */                                                                                                  
4324     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
4325             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
4326             int titleIndex) {                                                                            
4327                                                                                                          
4328         Bitmap icon = null;                                                                              
4329         final ShortcutInfo info = new ShortcutInfo();                                                    
4330         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
4331                                                                                                          
4332         // TODO: If there's an explicit component and we can't install that, delete it.                  
4333                                                                                                          
4334         info.title = c.getString(titleIndex);                                                            
4335                                                                                                          
4336         int iconType = c.getInt(iconTypeIndex);                                                          
4337         switch (iconType) {                                                                              
4338         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
4339             String packageName = c.getString(iconPackageIndex);                                          
4340             String resourceName = c.getString(iconResourceIndex);                                        
4341             PackageManager packageManager = context.getPackageManager();                                 
4342             info.customIcon = false;                                                                     
4343             // the resource                                                                              
4344             try {                                                                                        
4345                 Resources resources = packageManager.getResourcesForApplication(packageName);            
4346                 if (resources != null) {                                                                 
4347                     final int id = resources.getIdentifier(resourceName, null, null);                    
4348                     icon = Utilities.createIconBitmap(                                                   
4349                             mIconCache.getFullResIcon(resources, id), context);                          
4350                 }                                                                                        
4351             } catch (Exception e) {                                                                      
4352                 // drop this.  we have other places to look for icons                                    
4353             }                                                                                            
4354             // the db                                                                                    
4355             if (icon == null) {                                                                          
4356                 icon = getIconFromCursor(c, iconIndex, context);                                         
4357             }                                                                                            
4358             // the fallback icon                                                                         
4359             if (icon == null) {                                                                          
4360                 icon = getFallbackIcon();                                                                
4361                 info.usingFallbackIcon = true;                                                           
4362             }                                                                                            
4363             break;                                                                                       
4364         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
4365             icon = getIconFromCursor(c, iconIndex, context);                                             
4366             if (icon == null) {                                                                          
4367                 icon = getFallbackIcon();                                                                
4368                 info.customIcon = false;                                                                 
4369                 info.usingFallbackIcon = true;                                                           
4370             } else {                                                                                     
4371                 info.customIcon = true;                                                                  
4372             }                                                                                            
4373             break;                                                                                       
4374         default:                                                                                         
4375             icon = getFallbackIcon();                                                                    
4376             info.usingFallbackIcon = true;                                                               
4377             info.customIcon = false;                                                                     
4378             break;                                                                                       
4379         }                                                                                                
4380         info.setIcon(icon);                                                                              
4381         return info;                                                                                     
4382     }                                                                                                    
4383                                                                                                          
4384     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
4385         @SuppressWarnings("all") // suppress dead code warning                                           
4386         final boolean debug = false;                                                                     
4387         if (debug) {                                                                                     
4388             Log.d(TAG, "getIconFromCursor app="                                                          
4389                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
4390         }                                                                                                
4391         byte[] data = c.getBlob(iconIndex);                                                              
4392         try {                                                                                            
4393             return Utilities.createIconBitmap(                                                           
4394                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
4395         } catch (Exception e) {                                                                          
4396             return null;                                                                                 
4397         }                                                                                                
4398     }                                                                                                    
4399                                                                                                          
4400     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
4401             int cellX, int cellY, boolean notify) {                                                      
4402         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
4403         if (info == null) {                                                                              
4404             return null;                                                                                 
4405         }                                                                                                
4406         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
4407                                                                                                          
4408         return info;                                                                                     
4409     }                                                                                                    
4410                                                                                                          
4411     /**                                                                                                  
4412      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
4413      */                                                                                                  
4414     AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                        
4415             ComponentName component) {                                                                   
4416         List<AppWidgetProviderInfo> widgets =                                                            
4417             AppWidgetManager.getInstance(context).getInstalledProviders();                               
4418         for (AppWidgetProviderInfo info : widgets) {                                                     
4419             if (info.provider.equals(component)) {                                                       
4420                 return info;                                                                             
4421             }                                                                                            
4422         }                                                                                                
4423         return null;                                                                                     
4424     }                                                                                                    
4425                                                                                                          
4426     /**                                                                                                  
4427      * Returns a list of all the widgets that can handle configuration with a particular mimeType.       
4428      */                                                                                                  
4429     List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {        
4430         final PackageManager packageManager = context.getPackageManager();                               
4431         final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =                         
4432             new ArrayList<WidgetMimeTypeHandlerData>();                                                  
4433                                                                                                          
4434         final Intent supportsIntent =                                                                    
4435             new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);                         
4436         supportsIntent.setType(mimeType);                                                                
4437                                                                                                          
4438         // Create a set of widget configuration components that we can test against                      
4439         final List<AppWidgetProviderInfo> widgets =                                                      
4440             AppWidgetManager.getInstance(context).getInstalledProviders();                               
4441         final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =             
4442             new HashMap<ComponentName, AppWidgetProviderInfo>();                                         
4443         for (AppWidgetProviderInfo info : widgets) {                                                     
4444             configurationComponentToWidget.put(info.configure, info);                                    
4445         }                                                                                                
4446                                                                                                          
4447         // Run through each of the intents that can handle this type of clip data, and cross             
4448         // reference them with the components that are actual configuration components                   
4449         final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,        
4450                 PackageManager.MATCH_DEFAULT_ONLY);                                                      
4451         for (ResolveInfo info : activities) {                                                            
4452             final ActivityInfo activityInfo = info.activityInfo;                                         
4453             final ComponentName infoComponent = new ComponentName(activityInfo.packageName,              
4454                     activityInfo.name);                                                                  
4455             if (configurationComponentToWidget.containsKey(infoComponent)) {                             
4456                 supportedConfigurationActivities.add(                                                    
4457                         new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,                        
4458                                 configurationComponentToWidget.get(infoComponent)));                     
4459             }                                                                                            
4460         }                                                                                                
4461         return supportedConfigurationActivities;                                                         
4462     }                                                                                                    
4463                                                                                                          
4464     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
4465         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
4466         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
4467         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
4468                                                                                                          
4469         if (intent == null) {                                                                            
4470             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
4471             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
4472             return null;                                                                                 
4473         }                                                                                                
4474                                                                                                          
4475         Bitmap icon = null;                                                                              
4476         boolean customIcon = false;                                                                      
4477         ShortcutIconResource iconResource = null;                                                        
4478                                                                                                          
4479         if (bitmap != null && bitmap instanceof Bitmap) {                                                
4480             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
4481             customIcon = true;                                                                           
4482         } else {                                                                                         
4483 =======                                                                                                  
4484     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex) {                             
4485 >>>>>>> GitAnalyzerPlus_theirs                                                                           
4486         final ShortcutInfo info = new ShortcutInfo();                                                    
4487         info.user = UserHandleCompat.myUserHandle();                                                     
4488         mIconCache.getTitleAndIcon(info, intent, info.user, true);                                       
4489                                                                                                          
4490         if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {                                      
4491             String title = (cursor != null) ? cursor.getString(titleIndex) : null;                       
4492             if (!TextUtils.isEmpty(title)) {                                                             
4493                 info.title = title;                                                                      
4494             }                                                                                            
4495             info.status = ShortcutInfo.FLAG_RESTORED_ICON;                                               
4496         } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {                            
4497             if (TextUtils.isEmpty(info.title)) {                                                         
4498                 info.title = (cursor != null) ? cursor.getString(titleIndex) : "";                       
4499             }                                                                                            
4500             info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;                                             
4501         } else {                                                                                         
4502             throw new InvalidParameterException("Invalid restoreType " + promiseType);                   
4503         }                                                                                                
4504                                                                                                          
4505         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
4506                 info.title.toString(), info.user);                                                       
4507         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
4508 <<<<<<< GitAnalyzerPlus_ours                                                                             
4509         info.promisedIntent = intent;                                                                    
4510 ||||||| GitAnalyzerPlus_base                                                                             
4511                 getSortedWidgetsAndShortcuts(context);                                                   
4512             mHandler.post(new Runnable() {                                                               
4513                 @Override                                                                                
4514                 public void run() {                                                                      
4515                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
4516                     if (callbacks == cb && cb != null) {                                                 
4517                         callbacks.bindPackagesUpdated(widgetsAndShortcuts);                              
4518                     }                                                                                    
4519                 }                                                                                        
4520             });                                                                                          
4521                                                                                                          
4522             // Write all the logs to disk                                                                
4523             mHandler.post(new Runnable() {                                                               
4524                 public void run() {                                                                      
4525                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
4526                     if (callbacks == cb && cb != null) {                                                 
4527                         callbacks.dumpLogsToLocalData();                                                 
4528                     }                                                                                    
4529                 }                                                                                        
4530             });                                                                                          
4531         }                                                                                                
4532     }                                                                                                    
4533                                                                                                          
4534     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
4535     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
4536         PackageManager packageManager = context.getPackageManager();                                     
4537         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
4538         widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());       
4539         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
4540         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
4541         Collections.sort(widgetsAndShortcuts,                                                            
4542             new LauncherModel.WidgetAndShortcutNameComparator(packageManager));                          
4543         return widgetsAndShortcuts;                                                                      
4544     }                                                                                                    
4545                                                                                                          
4546     private static boolean isPackageDisabled(PackageManager pm, String packageName) {                    
4547         try {                                                                                            
4548             PackageInfo pi = pm.getPackageInfo(packageName, 0);                                          
4549             return !pi.applicationInfo.enabled;                                                          
4550         } catch (NameNotFoundException e) {                                                              
4551             // Fall through                                                                              
4552         }                                                                                                
4553         return false;                                                                                    
4554     }                                                                                                    
4555                                                                                                          
4556     public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {                 
4557         if (cn == null) {                                                                                
4558             return false;                                                                                
4559         }                                                                                                
4560         if (isPackageDisabled(pm, cn.getPackageName())) {                                                
4561             return false;                                                                                
4562         }                                                                                                
4563                                                                                                          
4564         try {                                                                                            
4565             // Check the activity                                                                        
4566             PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);                                  
4567             return (pm.getActivityInfo(cn, 0) != null);                                                  
4568         } catch (NameNotFoundException e) {                                                              
4569             return false;                                                                                
4570         }                                                                                                
4571     }                                                                                                    
4572                                                                                                          
4573     /**                                                                                                  
4574      * Make an ShortcutInfo object for a restored application or shortcut item that points               
4575      * to a package that is not yet installed on the system.                                             
4576      */                                                                                                  
4577     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {              
4578         final ShortcutInfo info = new ShortcutInfo();                                                    
4579         info.usingFallbackIcon = true;                                                                   
4580         info.setIcon(getFallbackIcon());                                                                 
4581         if (cursor != null) {                                                                            
4582             info.title =  cursor.getString(titleIndex);                                                  
4583         } else {                                                                                         
4584             info.title = "";                                                                             
4585         }                                                                                                
4586         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
4587         info.restoredIntent = intent;                                                                    
4588         return info;                                                                                     
4589     }                                                                                                    
4590                                                                                                          
4591     /**                                                                                                  
4592      * Make an Intent object for a restored application or shortcut item that points                     
4593      * to the market page for the item.                                                                  
4594      */                                                                                                  
4595     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
4596         final boolean debug = false;                                                                     
4597         ComponentName componentName = intent.getComponent();                                             
4598         Intent marketIntent = new Intent(Intent.ACTION_VIEW);                                            
4599         Uri marketUri = new Uri.Builder()                                                                
4600                 .scheme("market")                                                                        
4601                 .authority("details")                                                                    
4602                 .appendQueryParameter("id", componentName.getPackageName())                              
4603                 .build();                                                                                
4604         if (debug) Log.d(TAG, "manufactured intent uri: " + marketUri.toString());                       
4605         marketIntent.setData(marketUri);                                                                 
4606         return marketIntent;                                                                             
4607     }                                                                                                    
4608                                                                                                          
4609     /**                                                                                                  
4610      * This is called from the code that adds shortcuts from the intent receiver.  This                  
4611      * doesn't have a Cursor, but                                                                        
4612      */                                                                                                  
4613     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {        
4614         return getShortcutInfo(manager, intent, context, null, -1, -1, null);                            
4615     }                                                                                                    
4616                                                                                                          
4617     /**                                                                                                  
4618      * Make an ShortcutInfo object for a shortcut that is an application.                                
4619      *                                                                                                   
4620      * If c is not null, then it will be used to fill in missing data like the title and icon.           
4621      */                                                                                                  
4622     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,          
4623             Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {         
4624         ComponentName componentName = intent.getComponent();                                             
4625         final ShortcutInfo info = new ShortcutInfo();                                                    
4626         if (componentName != null && !isValidPackageComponent(manager, componentName)) {                 
4627             Log.d(TAG, "Invalid package found in getShortcutInfo: " + componentName);                    
4628             return null;                                                                                 
4629         } else {                                                                                         
4630             try {                                                                                        
4631                 PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);              
4632                 info.initFlagsAndFirstInstallTime(pi);                                                   
4633             } catch (NameNotFoundException e) {                                                          
4634                 Log.d(TAG, "getPackInfo failed for package " +                                           
4635                         componentName.getPackageName());                                                 
4636             }                                                                                            
4637         }                                                                                                
4638                                                                                                          
4639         // TODO: See if the PackageManager knows about this case.  If it doesn't                         
4640         // then return null & delete this.                                                               
4641                                                                                                          
4642         // the resource -- This may implicitly give us back the fallback icon,                           
4643         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
4644         // to avoid saving lots of copies of that in the database, and most apps                         
4645         // have icons anyway.                                                                            
4646                                                                                                          
4647         // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and      
4648         // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info     
4649         // via resolveActivity().                                                                        
4650         Bitmap icon = null;                                                                              
4651         ResolveInfo resolveInfo = null;                                                                  
4652         ComponentName oldComponent = intent.getComponent();                                              
4653         Intent newIntent = new Intent(intent.getAction(), null);                                         
4654         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
4655         newIntent.setPackage(oldComponent.getPackageName());                                             
4656         List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);                           
4657         for (ResolveInfo i : infos) {                                                                    
4658             ComponentName cn = new ComponentName(i.activityInfo.packageName,                             
4659                     i.activityInfo.name);                                                                
4660             if (cn.equals(oldComponent)) {                                                               
4661                 resolveInfo = i;                                                                         
4662             }                                                                                            
4663         }                                                                                                
4664         if (resolveInfo == null) {                                                                       
4665             resolveInfo = manager.resolveActivity(intent, 0);                                            
4666         }                                                                                                
4667         if (resolveInfo != null) {                                                                       
4668             icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);                           
4669         }                                                                                                
4670         // the db                                                                                        
4671         if (icon == null) {                                                                              
4672             if (c != null) {                                                                             
4673                 icon = getIconFromCursor(c, iconIndex, context);                                         
4674             }                                                                                            
4675         }                                                                                                
4676         // the fallback icon                                                                             
4677         if (icon == null) {                                                                              
4678             icon = getFallbackIcon();                                                                    
4679             info.usingFallbackIcon = true;                                                               
4680         }                                                                                                
4681         info.setIcon(icon);                                                                              
4682                                                                                                          
4683         // from the resource                                                                             
4684         if (resolveInfo != null) {                                                                       
4685             ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);              
4686             if (labelCache != null && labelCache.containsKey(key)) {                                     
4687                 info.title = labelCache.get(key);                                                        
4688             } else {                                                                                     
4689                 info.title = resolveInfo.activityInfo.loadLabel(manager);                                
4690                 if (labelCache != null) {                                                                
4691                     labelCache.put(key, info.title);                                                     
4692                 }                                                                                        
4693             }                                                                                            
4694         }                                                                                                
4695         // from the db                                                                                   
4696         if (info.title == null) {                                                                        
4697             if (c != null) {                                                                             
4698                 info.title =  c.getString(titleIndex);                                                   
4699             }                                                                                            
4700         }                                                                                                
4701         // fall back to the class name of the activity                                                   
4702         if (info.title == null) {                                                                        
4703             info.title = componentName.getClassName();                                                   
4704         }                                                                                                
4705         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
4706         return info;                                                                                     
4707     }                                                                                                    
4708                                                                                                          
4709     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
4710             ItemInfoFilter f) {                                                                          
4711         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
4712         for (ItemInfo i : infos) {                                                                       
4713             if (i instanceof ShortcutInfo) {                                                             
4714                 ShortcutInfo info = (ShortcutInfo) i;                                                    
4715                 ComponentName cn = info.intent.getComponent();                                           
4716                 if (cn != null && f.filterItem(null, info, cn)) {                                        
4717                     filtered.add(info);                                                                  
4718                 }                                                                                        
4719             } else if (i instanceof FolderInfo) {                                                        
4720                 FolderInfo info = (FolderInfo) i;                                                        
4721                 for (ShortcutInfo s : info.contents) {                                                   
4722                     ComponentName cn = s.intent.getComponent();                                          
4723                     if (cn != null && f.filterItem(info, s, cn)) {                                       
4724                         filtered.add(s);                                                                 
4725                     }                                                                                    
4726                 }                                                                                        
4727             } else if (i instanceof LauncherAppWidgetInfo) {                                             
4728                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
4729                 ComponentName cn = info.providerName;                                                    
4730                 if (cn != null && f.filterItem(null, info, cn)) {                                        
4731                     filtered.add(info);                                                                  
4732                 }                                                                                        
4733             }                                                                                            
4734         }                                                                                                
4735         return new ArrayList<ItemInfo>(filtered);                                                        
4736     }                                                                                                    
4737                                                                                                          
4738     private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {                             
4739         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
4740             @Override                                                                                    
4741             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
4742                 return cn.getPackageName().equals(pn);                                                   
4743             }                                                                                            
4744         };                                                                                               
4745         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
4746     }                                                                                                    
4747                                                                                                          
4748     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {                 
4749         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
4750             @Override                                                                                    
4751             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
4752                 return cn.equals(cname);                                                                 
4753             }                                                                                            
4754         };                                                                                               
4755         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
4756     }                                                                                                    
4757                                                                                                          
4758     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
4759         if (i instanceof ShortcutInfo) {                                                                 
4760             ShortcutInfo info = (ShortcutInfo) i;                                                        
4761             // We need to check for ACTION_MAIN otherwise getComponent() might                           
4762             // return null for some shortcuts (for instance, for shortcuts to                            
4763             // web pages.)                                                                               
4764             Intent intent = info.intent;                                                                 
4765             ComponentName name = intent.getComponent();                                                  
4766             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
4767                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
4768                 return true;                                                                             
4769             }                                                                                            
4770             // placeholder shortcuts get special treatment, let them through too.                        
4771             if (info.getRestoredIntent() != null) {                                                      
4772                 return true;                                                                             
4773             }                                                                                            
4774         }                                                                                                
4775         return false;                                                                                    
4776     }                                                                                                    
4777                                                                                                          
4778     /**                                                                                                  
4779      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
4780      */                                                                                                  
4781     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
4782             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
4783             int titleIndex) {                                                                            
4784                                                                                                          
4785         Bitmap icon = null;                                                                              
4786         final ShortcutInfo info = new ShortcutInfo();                                                    
4787         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
4788                                                                                                          
4789         // TODO: If there's an explicit component and we can't install that, delete it.                  
4790                                                                                                          
4791         info.title = c.getString(titleIndex);                                                            
4792                                                                                                          
4793         int iconType = c.getInt(iconTypeIndex);                                                          
4794         switch (iconType) {                                                                              
4795         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
4796             String packageName = c.getString(iconPackageIndex);                                          
4797             String resourceName = c.getString(iconResourceIndex);                                        
4798             PackageManager packageManager = context.getPackageManager();                                 
4799             info.customIcon = false;                                                                     
4800             // the resource                                                                              
4801             try {                                                                                        
4802                 Resources resources = packageManager.getResourcesForApplication(packageName);            
4803                 if (resources != null) {                                                                 
4804                     final int id = resources.getIdentifier(resourceName, null, null);                    
4805                     icon = Utilities.createIconBitmap(                                                   
4806                             mIconCache.getFullResIcon(resources, id), context);                          
4807                 }                                                                                        
4808             } catch (Exception e) {                                                                      
4809                 // drop this.  we have other places to look for icons                                    
4810             }                                                                                            
4811             // the db                                                                                    
4812             if (icon == null) {                                                                          
4813                 icon = getIconFromCursor(c, iconIndex, context);                                         
4814             }                                                                                            
4815             // the fallback icon                                                                         
4816             if (icon == null) {                                                                          
4817                 icon = getFallbackIcon();                                                                
4818                 info.usingFallbackIcon = true;                                                           
4819             }                                                                                            
4820             break;                                                                                       
4821         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
4822             icon = getIconFromCursor(c, iconIndex, context);                                             
4823             if (icon == null) {                                                                          
4824                 icon = getFallbackIcon();                                                                
4825                 info.customIcon = false;                                                                 
4826                 info.usingFallbackIcon = true;                                                           
4827             } else {                                                                                     
4828                 info.customIcon = true;                                                                  
4829             }                                                                                            
4830             break;                                                                                       
4831         default:                                                                                         
4832             icon = getFallbackIcon();                                                                    
4833             info.usingFallbackIcon = true;                                                               
4834             info.customIcon = false;                                                                     
4835             break;                                                                                       
4836         }                                                                                                
4837         info.setIcon(icon);                                                                              
4838         return info;                                                                                     
4839     }                                                                                                    
4840                                                                                                          
4841     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
4842         @SuppressWarnings("all") // suppress dead code warning                                           
4843         final boolean debug = false;                                                                     
4844         if (debug) {                                                                                     
4845             Log.d(TAG, "getIconFromCursor app="                                                          
4846                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
4847         }                                                                                                
4848         byte[] data = c.getBlob(iconIndex);                                                              
4849         try {                                                                                            
4850             return Utilities.createIconBitmap(                                                           
4851                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
4852         } catch (Exception e) {                                                                          
4853             return null;                                                                                 
4854         }                                                                                                
4855     }                                                                                                    
4856                                                                                                          
4857     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
4858             int cellX, int cellY, boolean notify) {                                                      
4859         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
4860         if (info == null) {                                                                              
4861             return null;                                                                                 
4862         }                                                                                                
4863         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
4864                                                                                                          
4865         return info;                                                                                     
4866     }                                                                                                    
4867                                                                                                          
4868     /**                                                                                                  
4869      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
4870      */                                                                                                  
4871     AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                        
4872             ComponentName component) {                                                                   
4873         List<AppWidgetProviderInfo> widgets =                                                            
4874             AppWidgetManager.getInstance(context).getInstalledProviders();                               
4875         for (AppWidgetProviderInfo info : widgets) {                                                     
4876             if (info.provider.equals(component)) {                                                       
4877                 return info;                                                                             
4878             }                                                                                            
4879         }                                                                                                
4880         return null;                                                                                     
4881     }                                                                                                    
4882                                                                                                          
4883     /**                                                                                                  
4884      * Returns a list of all the widgets that can handle configuration with a particular mimeType.       
4885      */                                                                                                  
4886     List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {        
4887         final PackageManager packageManager = context.getPackageManager();                               
4888         final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =                         
4889             new ArrayList<WidgetMimeTypeHandlerData>();                                                  
4890                                                                                                          
4891         final Intent supportsIntent =                                                                    
4892             new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);                         
4893         supportsIntent.setType(mimeType);                                                                
4894                                                                                                          
4895         // Create a set of widget configuration components that we can test against                      
4896         final List<AppWidgetProviderInfo> widgets =                                                      
4897             AppWidgetManager.getInstance(context).getInstalledProviders();                               
4898         final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =             
4899             new HashMap<ComponentName, AppWidgetProviderInfo>();                                         
4900         for (AppWidgetProviderInfo info : widgets) {                                                     
4901             configurationComponentToWidget.put(info.configure, info);                                    
4902         }                                                                                                
4903                                                                                                          
4904         // Run through each of the intents that can handle this type of clip data, and cross             
4905         // reference them with the components that are actual configuration components                   
4906         final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,        
4907                 PackageManager.MATCH_DEFAULT_ONLY);                                                      
4908         for (ResolveInfo info : activities) {                                                            
4909             final ActivityInfo activityInfo = info.activityInfo;                                         
4910             final ComponentName infoComponent = new ComponentName(activityInfo.packageName,              
4911                     activityInfo.name);                                                                  
4912             if (configurationComponentToWidget.containsKey(infoComponent)) {                             
4913                 supportedConfigurationActivities.add(                                                    
4914                         new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,                        
4915                                 configurationComponentToWidget.get(infoComponent)));                     
4916             }                                                                                            
4917         }                                                                                                
4918         return supportedConfigurationActivities;                                                         
4919     }                                                                                                    
4920                                                                                                          
4921     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
4922         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
4923         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
4924         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
4925                                                                                                          
4926         if (intent == null) {                                                                            
4927             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
4928             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
4929             return null;                                                                                 
4930         }                                                                                                
4931                                                                                                          
4932         Bitmap icon = null;                                                                              
4933         boolean customIcon = false;                                                                      
4934         ShortcutIconResource iconResource = null;                                                        
4935                                                                                                          
4936         if (bitmap != null && bitmap instanceof Bitmap) {                                                
4937             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
4938             customIcon = true;                                                                           
4939         } else {                                                                                         
4940             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
4941             if (extra != null && extra instanceof ShortcutIconResource) {                                
4942                 try {                                                                                    
4943                     iconResource = (ShortcutIconResource) extra;                                         
4944                     final PackageManager packageManager = context.getPackageManager();                   
4945                     Resources resources = packageManager.getResourcesForApplication(                     
4946                             iconResource.packageName);                                                   
4947                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
4948                     icon = Utilities.createIconBitmap(                                                   
4949                             mIconCache.getFullResIcon(resources, id), context);                          
4950                 } catch (Exception e) {                                                                  
4951                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
4952                 }                                                                                        
4953             }                                                                                            
4954         }                                                                                                
4955                                                                                                          
4956         final ShortcutInfo info = new ShortcutInfo();                                                    
4957                                                                                                          
4958         if (icon == null) {                                                                              
4959             if (fallbackIcon != null) {                                                                  
4960                 icon = fallbackIcon;                                                                     
4961             } else {                                                                                     
4962                 icon = getFallbackIcon();                                                                
4963 =======                                                                                                  
4964 >>>>>>> GitAnalyzerPlus_theirs                                                                           
4965         return info;                                                                                     
4966     }                                                                                                    
4967                                                                                                          
4968     /**                                                                                                  
4969      * Make an Intent object for a restored application or shortcut item that points                     
4970      * to the market page for the item.                                                                  
4971      */                                                                                                  
4972     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
4973         ComponentName componentName = intent.getComponent();                                             
4974         return getMarketIntent(componentName.getPackageName());                                          
4975     }                                                                                                    
4976                                                                                                          
4977     static Intent getMarketIntent(String packageName) {                                                  
4978         return new Intent(Intent.ACTION_VIEW)                                                            
4979             .setData(new Uri.Builder()                                                                   
4980                 .scheme("market")                                                                        
4981                 .authority("details")                                                                    
4982 <<<<<<< GitAnalyzerPlus_ours                                                                             
4983                 .appendQueryParameter("id", packageName)                                                 
4984                 .build());                                                                               
4985 ||||||| GitAnalyzerPlus_base                                                                             
4986                 public void run() {                                                                      
4987                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
4988                     if (callbacks == cb && cb != null) {                                                 
4989                         callbacks.dumpLogsToLocalData();                                                 
4990                     }                                                                                    
4991                 }                                                                                        
4992             });                                                                                          
4993         }                                                                                                
4994     }                                                                                                    
4995                                                                                                          
4996     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
4997     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
4998         PackageManager packageManager = context.getPackageManager();                                     
4999         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
5000         widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());       
5001         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
5002         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
5003         Collections.sort(widgetsAndShortcuts,                                                            
5004             new LauncherModel.WidgetAndShortcutNameComparator(packageManager));                          
5005         return widgetsAndShortcuts;                                                                      
5006     }                                                                                                    
5007                                                                                                          
5008     private static boolean isPackageDisabled(PackageManager pm, String packageName) {                    
5009         try {                                                                                            
5010             PackageInfo pi = pm.getPackageInfo(packageName, 0);                                          
5011             return !pi.applicationInfo.enabled;                                                          
5012         } catch (NameNotFoundException e) {                                                              
5013             // Fall through                                                                              
5014         }                                                                                                
5015         return false;                                                                                    
5016     }                                                                                                    
5017                                                                                                          
5018     public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {                 
5019         if (cn == null) {                                                                                
5020             return false;                                                                                
5021         }                                                                                                
5022         if (isPackageDisabled(pm, cn.getPackageName())) {                                                
5023             return false;                                                                                
5024         }                                                                                                
5025                                                                                                          
5026         try {                                                                                            
5027             // Check the activity                                                                        
5028             PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);                                  
5029             return (pm.getActivityInfo(cn, 0) != null);                                                  
5030         } catch (NameNotFoundException e) {                                                              
5031             return false;                                                                                
5032         }                                                                                                
5033     }                                                                                                    
5034                                                                                                          
5035     /**                                                                                                  
5036      * Make an ShortcutInfo object for a restored application or shortcut item that points               
5037      * to a package that is not yet installed on the system.                                             
5038      */                                                                                                  
5039     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent) {              
5040         final ShortcutInfo info = new ShortcutInfo();                                                    
5041         info.usingFallbackIcon = true;                                                                   
5042         info.setIcon(getFallbackIcon());                                                                 
5043         if (cursor != null) {                                                                            
5044             info.title =  cursor.getString(titleIndex);                                                  
5045         } else {                                                                                         
5046             info.title = "";                                                                             
5047         }                                                                                                
5048         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
5049         info.restoredIntent = intent;                                                                    
5050         return info;                                                                                     
5051     }                                                                                                    
5052                                                                                                          
5053     /**                                                                                                  
5054      * Make an Intent object for a restored application or shortcut item that points                     
5055      * to the market page for the item.                                                                  
5056      */                                                                                                  
5057     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
5058         final boolean debug = false;                                                                     
5059         ComponentName componentName = intent.getComponent();                                             
5060         Intent marketIntent = new Intent(Intent.ACTION_VIEW);                                            
5061         Uri marketUri = new Uri.Builder()                                                                
5062                 .scheme("market")                                                                        
5063                 .authority("details")                                                                    
5064                 .appendQueryParameter("id", componentName.getPackageName())                              
5065                 .build();                                                                                
5066         if (debug) Log.d(TAG, "manufactured intent uri: " + marketUri.toString());                       
5067         marketIntent.setData(marketUri);                                                                 
5068         return marketIntent;                                                                             
5069     }                                                                                                    
5070                                                                                                          
5071     /**                                                                                                  
5072      * This is called from the code that adds shortcuts from the intent receiver.  This                  
5073      * doesn't have a Cursor, but                                                                        
5074      */                                                                                                  
5075     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {        
5076         return getShortcutInfo(manager, intent, context, null, -1, -1, null);                            
5077     }                                                                                                    
5078                                                                                                          
5079     /**                                                                                                  
5080      * Make an ShortcutInfo object for a shortcut that is an application.                                
5081      *                                                                                                   
5082      * If c is not null, then it will be used to fill in missing data like the title and icon.           
5083      */                                                                                                  
5084     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,          
5085             Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {         
5086         ComponentName componentName = intent.getComponent();                                             
5087         final ShortcutInfo info = new ShortcutInfo();                                                    
5088         if (componentName != null && !isValidPackageComponent(manager, componentName)) {                 
5089             Log.d(TAG, "Invalid package found in getShortcutInfo: " + componentName);                    
5090             return null;                                                                                 
5091         } else {                                                                                         
5092             try {                                                                                        
5093                 PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);              
5094                 info.initFlagsAndFirstInstallTime(pi);                                                   
5095             } catch (NameNotFoundException e) {                                                          
5096                 Log.d(TAG, "getPackInfo failed for package " +                                           
5097                         componentName.getPackageName());                                                 
5098             }                                                                                            
5099         }                                                                                                
5100                                                                                                          
5101         // TODO: See if the PackageManager knows about this case.  If it doesn't                         
5102         // then return null & delete this.                                                               
5103                                                                                                          
5104         // the resource -- This may implicitly give us back the fallback icon,                           
5105         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
5106         // to avoid saving lots of copies of that in the database, and most apps                         
5107         // have icons anyway.                                                                            
5108                                                                                                          
5109         // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and      
5110         // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info     
5111         // via resolveActivity().                                                                        
5112         Bitmap icon = null;                                                                              
5113         ResolveInfo resolveInfo = null;                                                                  
5114         ComponentName oldComponent = intent.getComponent();                                              
5115         Intent newIntent = new Intent(intent.getAction(), null);                                         
5116         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
5117         newIntent.setPackage(oldComponent.getPackageName());                                             
5118         List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);                           
5119         for (ResolveInfo i : infos) {                                                                    
5120             ComponentName cn = new ComponentName(i.activityInfo.packageName,                             
5121                     i.activityInfo.name);                                                                
5122             if (cn.equals(oldComponent)) {                                                               
5123                 resolveInfo = i;                                                                         
5124             }                                                                                            
5125         }                                                                                                
5126         if (resolveInfo == null) {                                                                       
5127             resolveInfo = manager.resolveActivity(intent, 0);                                            
5128         }                                                                                                
5129         if (resolveInfo != null) {                                                                       
5130             icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);                           
5131         }                                                                                                
5132         // the db                                                                                        
5133         if (icon == null) {                                                                              
5134             if (c != null) {                                                                             
5135                 icon = getIconFromCursor(c, iconIndex, context);                                         
5136             }                                                                                            
5137         }                                                                                                
5138         // the fallback icon                                                                             
5139         if (icon == null) {                                                                              
5140             icon = getFallbackIcon();                                                                    
5141             info.usingFallbackIcon = true;                                                               
5142         }                                                                                                
5143         info.setIcon(icon);                                                                              
5144                                                                                                          
5145         // from the resource                                                                             
5146         if (resolveInfo != null) {                                                                       
5147             ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);              
5148             if (labelCache != null && labelCache.containsKey(key)) {                                     
5149                 info.title = labelCache.get(key);                                                        
5150             } else {                                                                                     
5151                 info.title = resolveInfo.activityInfo.loadLabel(manager);                                
5152                 if (labelCache != null) {                                                                
5153                     labelCache.put(key, info.title);                                                     
5154                 }                                                                                        
5155             }                                                                                            
5156         }                                                                                                
5157         // from the db                                                                                   
5158         if (info.title == null) {                                                                        
5159             if (c != null) {                                                                             
5160                 info.title =  c.getString(titleIndex);                                                   
5161             }                                                                                            
5162         }                                                                                                
5163         // fall back to the class name of the activity                                                   
5164         if (info.title == null) {                                                                        
5165             info.title = componentName.getClassName();                                                   
5166         }                                                                                                
5167         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
5168         return info;                                                                                     
5169     }                                                                                                    
5170                                                                                                          
5171     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
5172             ItemInfoFilter f) {                                                                          
5173         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
5174         for (ItemInfo i : infos) {                                                                       
5175             if (i instanceof ShortcutInfo) {                                                             
5176                 ShortcutInfo info = (ShortcutInfo) i;                                                    
5177                 ComponentName cn = info.intent.getComponent();                                           
5178                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5179                     filtered.add(info);                                                                  
5180                 }                                                                                        
5181             } else if (i instanceof FolderInfo) {                                                        
5182                 FolderInfo info = (FolderInfo) i;                                                        
5183                 for (ShortcutInfo s : info.contents) {                                                   
5184                     ComponentName cn = s.intent.getComponent();                                          
5185                     if (cn != null && f.filterItem(info, s, cn)) {                                       
5186                         filtered.add(s);                                                                 
5187                     }                                                                                    
5188                 }                                                                                        
5189             } else if (i instanceof LauncherAppWidgetInfo) {                                             
5190                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
5191                 ComponentName cn = info.providerName;                                                    
5192                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5193                     filtered.add(info);                                                                  
5194                 }                                                                                        
5195             }                                                                                            
5196         }                                                                                                
5197         return new ArrayList<ItemInfo>(filtered);                                                        
5198     }                                                                                                    
5199                                                                                                          
5200     private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {                             
5201         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
5202             @Override                                                                                    
5203             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
5204                 return cn.getPackageName().equals(pn);                                                   
5205             }                                                                                            
5206         };                                                                                               
5207         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
5208     }                                                                                                    
5209                                                                                                          
5210     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {                 
5211         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
5212             @Override                                                                                    
5213             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
5214                 return cn.equals(cname);                                                                 
5215             }                                                                                            
5216         };                                                                                               
5217         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
5218     }                                                                                                    
5219                                                                                                          
5220     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
5221         if (i instanceof ShortcutInfo) {                                                                 
5222             ShortcutInfo info = (ShortcutInfo) i;                                                        
5223             // We need to check for ACTION_MAIN otherwise getComponent() might                           
5224             // return null for some shortcuts (for instance, for shortcuts to                            
5225             // web pages.)                                                                               
5226             Intent intent = info.intent;                                                                 
5227             ComponentName name = intent.getComponent();                                                  
5228             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
5229                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
5230                 return true;                                                                             
5231             }                                                                                            
5232             // placeholder shortcuts get special treatment, let them through too.                        
5233             if (info.getRestoredIntent() != null) {                                                      
5234                 return true;                                                                             
5235             }                                                                                            
5236         }                                                                                                
5237         return false;                                                                                    
5238     }                                                                                                    
5239                                                                                                          
5240     /**                                                                                                  
5241      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
5242      */                                                                                                  
5243     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
5244             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
5245             int titleIndex) {                                                                            
5246                                                                                                          
5247         Bitmap icon = null;                                                                              
5248         final ShortcutInfo info = new ShortcutInfo();                                                    
5249         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
5250                                                                                                          
5251         // TODO: If there's an explicit component and we can't install that, delete it.                  
5252                                                                                                          
5253         info.title = c.getString(titleIndex);                                                            
5254                                                                                                          
5255         int iconType = c.getInt(iconTypeIndex);                                                          
5256         switch (iconType) {                                                                              
5257         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
5258             String packageName = c.getString(iconPackageIndex);                                          
5259             String resourceName = c.getString(iconResourceIndex);                                        
5260             PackageManager packageManager = context.getPackageManager();                                 
5261             info.customIcon = false;                                                                     
5262             // the resource                                                                              
5263             try {                                                                                        
5264                 Resources resources = packageManager.getResourcesForApplication(packageName);            
5265                 if (resources != null) {                                                                 
5266                     final int id = resources.getIdentifier(resourceName, null, null);                    
5267                     icon = Utilities.createIconBitmap(                                                   
5268                             mIconCache.getFullResIcon(resources, id), context);                          
5269                 }                                                                                        
5270             } catch (Exception e) {                                                                      
5271                 // drop this.  we have other places to look for icons                                    
5272             }                                                                                            
5273             // the db                                                                                    
5274             if (icon == null) {                                                                          
5275                 icon = getIconFromCursor(c, iconIndex, context);                                         
5276             }                                                                                            
5277             // the fallback icon                                                                         
5278             if (icon == null) {                                                                          
5279                 icon = getFallbackIcon();                                                                
5280                 info.usingFallbackIcon = true;                                                           
5281             }                                                                                            
5282             break;                                                                                       
5283         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
5284             icon = getIconFromCursor(c, iconIndex, context);                                             
5285             if (icon == null) {                                                                          
5286                 icon = getFallbackIcon();                                                                
5287                 info.customIcon = false;                                                                 
5288                 info.usingFallbackIcon = true;                                                           
5289             } else {                                                                                     
5290                 info.customIcon = true;                                                                  
5291             }                                                                                            
5292             break;                                                                                       
5293         default:                                                                                         
5294             icon = getFallbackIcon();                                                                    
5295             info.usingFallbackIcon = true;                                                               
5296             info.customIcon = false;                                                                     
5297             break;                                                                                       
5298         }                                                                                                
5299         info.setIcon(icon);                                                                              
5300         return info;                                                                                     
5301     }                                                                                                    
5302                                                                                                          
5303     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
5304         @SuppressWarnings("all") // suppress dead code warning                                           
5305         final boolean debug = false;                                                                     
5306         if (debug) {                                                                                     
5307             Log.d(TAG, "getIconFromCursor app="                                                          
5308                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
5309         }                                                                                                
5310         byte[] data = c.getBlob(iconIndex);                                                              
5311         try {                                                                                            
5312             return Utilities.createIconBitmap(                                                           
5313                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
5314         } catch (Exception e) {                                                                          
5315             return null;                                                                                 
5316         }                                                                                                
5317     }                                                                                                    
5318                                                                                                          
5319     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
5320             int cellX, int cellY, boolean notify) {                                                      
5321         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
5322         if (info == null) {                                                                              
5323             return null;                                                                                 
5324         }                                                                                                
5325         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
5326                                                                                                          
5327         return info;                                                                                     
5328     }                                                                                                    
5329                                                                                                          
5330     /**                                                                                                  
5331      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
5332      */                                                                                                  
5333     AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                        
5334             ComponentName component) {                                                                   
5335         List<AppWidgetProviderInfo> widgets =                                                            
5336             AppWidgetManager.getInstance(context).getInstalledProviders();                               
5337         for (AppWidgetProviderInfo info : widgets) {                                                     
5338             if (info.provider.equals(component)) {                                                       
5339                 return info;                                                                             
5340             }                                                                                            
5341         }                                                                                                
5342         return null;                                                                                     
5343     }                                                                                                    
5344                                                                                                          
5345     /**                                                                                                  
5346      * Returns a list of all the widgets that can handle configuration with a particular mimeType.       
5347      */                                                                                                  
5348     List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {        
5349         final PackageManager packageManager = context.getPackageManager();                               
5350         final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =                         
5351             new ArrayList<WidgetMimeTypeHandlerData>();                                                  
5352                                                                                                          
5353         final Intent supportsIntent =                                                                    
5354             new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);                         
5355         supportsIntent.setType(mimeType);                                                                
5356                                                                                                          
5357         // Create a set of widget configuration components that we can test against                      
5358         final List<AppWidgetProviderInfo> widgets =                                                      
5359             AppWidgetManager.getInstance(context).getInstalledProviders();                               
5360         final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =             
5361             new HashMap<ComponentName, AppWidgetProviderInfo>();                                         
5362         for (AppWidgetProviderInfo info : widgets) {                                                     
5363             configurationComponentToWidget.put(info.configure, info);                                    
5364         }                                                                                                
5365                                                                                                          
5366         // Run through each of the intents that can handle this type of clip data, and cross             
5367         // reference them with the components that are actual configuration components                   
5368         final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,        
5369                 PackageManager.MATCH_DEFAULT_ONLY);                                                      
5370         for (ResolveInfo info : activities) {                                                            
5371             final ActivityInfo activityInfo = info.activityInfo;                                         
5372             final ComponentName infoComponent = new ComponentName(activityInfo.packageName,              
5373                     activityInfo.name);                                                                  
5374             if (configurationComponentToWidget.containsKey(infoComponent)) {                             
5375                 supportedConfigurationActivities.add(                                                    
5376                         new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,                        
5377                                 configurationComponentToWidget.get(infoComponent)));                     
5378             }                                                                                            
5379         }                                                                                                
5380         return supportedConfigurationActivities;                                                         
5381     }                                                                                                    
5382                                                                                                          
5383     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
5384         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
5385         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
5386         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
5387                                                                                                          
5388         if (intent == null) {                                                                            
5389             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
5390             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
5391             return null;                                                                                 
5392         }                                                                                                
5393                                                                                                          
5394         Bitmap icon = null;                                                                              
5395         boolean customIcon = false;                                                                      
5396         ShortcutIconResource iconResource = null;                                                        
5397                                                                                                          
5398         if (bitmap != null && bitmap instanceof Bitmap) {                                                
5399             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
5400             customIcon = true;                                                                           
5401         } else {                                                                                         
5402             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
5403             if (extra != null && extra instanceof ShortcutIconResource) {                                
5404                 try {                                                                                    
5405                     iconResource = (ShortcutIconResource) extra;                                         
5406                     final PackageManager packageManager = context.getPackageManager();                   
5407                     Resources resources = packageManager.getResourcesForApplication(                     
5408                             iconResource.packageName);                                                   
5409                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
5410                     icon = Utilities.createIconBitmap(                                                   
5411                             mIconCache.getFullResIcon(resources, id), context);                          
5412                 } catch (Exception e) {                                                                  
5413                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
5414                 }                                                                                        
5415             }                                                                                            
5416         }                                                                                                
5417                                                                                                          
5418         final ShortcutInfo info = new ShortcutInfo();                                                    
5419                                                                                                          
5420         if (icon == null) {                                                                              
5421             if (fallbackIcon != null) {                                                                  
5422                 icon = fallbackIcon;                                                                     
5423             } else {                                                                                     
5424                 icon = getFallbackIcon();                                                                
5425                 info.usingFallbackIcon = true;                                                           
5426             }                                                                                            
5427         }                                                                                                
5428         info.setIcon(icon);                                                                              
5429                                                                                                          
5430         info.title = name;                                                                               
5431         info.intent = intent;                                                                            
5432         info.customIcon = customIcon;                                                                    
5433         info.iconResource = iconResource;                                                                
5434                                                                                                          
5435         return info;                                                                                     
5436     }                                                                                                    
5437                                                                                                          
5438     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,             
5439             int iconIndex) {                                                                             
5440         // If apps can't be on SD, don't even bother.                                                    
5441         if (!mAppsCanBeOnRemoveableStorage) {                                                            
5442             return false;                                                                                
5443         }                                                                                                
5444 =======                                                                                                  
5445                 .appendQueryParameter("id", componentName.getPackageName())                              
5446                 .build();                                                                                
5447         Log.d(TAG, "manufactured intent uri: " + marketUri.toString());                                  
5448         marketIntent.setData(marketUri);                                                                 
5449         return marketIntent;                                                                             
5450 >>>>>>> GitAnalyzerPlus_theirs                                                                           
5451     }                                                                                                    
5452                                                                                                          
5453     /**                                                                                                  
5454      * This is called from the code that adds shortcuts from the intent receiver.  This                  
5455      * doesn't have a Cursor, but                                                                        
5456      */                                                                                                  
5457     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                           
5458             UserHandleCompat user, Context context) {                                                    
5459         return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);               
5460     }                                                                                                    
5461                                                                                                          
5462     /**                                                                                                  
5463      * Make an ShortcutInfo object for a shortcut that is an application.                                
5464      *                                                                                                   
5465      * If c is not null, then it will be used to fill in missing data like the title and icon.           
5466      */                                                                                                  
5467     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                           
5468             UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,             
5469             HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {                      
5470         if (user == null) {                                                                              
5471             Log.d(TAG, "Null user found in getShortcutInfo");                                            
5472             return null;                                                                                 
5473         }                                                                                                
5474                                                                                                          
5475         ComponentName componentName = intent.getComponent();                                             
5476         if (componentName == null) {                                                                     
5477             Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);                  
5478             return null;                                                                                 
5479         }                                                                                                
5480                                                                                                          
5481         Intent newIntent = new Intent(intent.getAction(), null);                                         
5482         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
5483         newIntent.setComponent(componentName);                                                           
5484         LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);                 
5485         if ((lai == null) && !allowMissingTarget) {                                                      
5486             Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);                   
5487             return null;                                                                                 
5488         }                                                                                                
5489                                                                                                          
5490         final ShortcutInfo info = new ShortcutInfo();                                                    
5491                                                                                                          
5492         // the resource -- This may implicitly give us back the fallback icon,                           
5493         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
5494         // to avoid saving lots of copies of that in the database, and most apps                         
5495         // have icons anyway.                                                                            
5496         Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);                                
5497                                                                                                          
5498         // the db                                                                                        
5499         if (icon == null) {                                                                              
5500             if (c != null) {                                                                             
5501                 icon = getIconFromCursor(c, iconIndex, context);                                         
5502             }                                                                                            
5503         }                                                                                                
5504         // the fallback icon                                                                             
5505         if (icon == null) {                                                                              
5506             icon = mIconCache.getDefaultIcon(user);                                                      
5507             info.usingFallbackIcon = true;                                                               
5508         }                                                                                                
5509         info.setIcon(icon);                                                                              
5510                                                                                                          
5511         // From the cache.                                                                               
5512         if (labelCache != null) {                                                                        
5513             info.title = labelCache.get(componentName);                                                  
5514         }                                                                                                
5515                                                                                                          
5516         // from the resource                                                                             
5517         if (info.title == null && lai != null) {                                                         
5518             info.title = lai.getLabel();                                                                 
5519             if (labelCache != null) {                                                                    
5520                 labelCache.put(componentName, info.title);                                               
5521             }                                                                                            
5522         }                                                                                                
5523         // from the db                                                                                   
5524         if (info.title == null) {                                                                        
5525             if (c != null) {                                                                             
5526                 info.title =  c.getString(titleIndex);                                                   
5527             }                                                                                            
5528         }                                                                                                
5529         // fall back to the class name of the activity                                                   
5530         if (info.title == null) {                                                                        
5531             info.title = componentName.getClassName();                                                   
5532         }                                                                                                
5533         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
5534         info.user = user;                                                                                
5535         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
5536                 info.title.toString(), info.user);                                                       
5537         return info;                                                                                     
5538     }                                                                                                    
5539                                                                                                          
5540     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
5541             ItemInfoFilter f) {                                                                          
5542         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
5543         for (ItemInfo i : infos) {                                                                       
5544             if (i instanceof ShortcutInfo) {                                                             
5545                 ShortcutInfo info = (ShortcutInfo) i;                                                    
5546                 ComponentName cn = info.getTargetComponent();                                            
5547                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5548                     filtered.add(info);                                                                  
5549                 }                                                                                        
5550             } else if (i instanceof FolderInfo) {                                                        
5551                 FolderInfo info = (FolderInfo) i;                                                        
5552                 for (ShortcutInfo s : info.contents) {                                                   
5553                     ComponentName cn = s.getTargetComponent();                                           
5554                     if (cn != null && f.filterItem(info, s, cn)) {                                       
5555                         filtered.add(s);                                                                 
5556                     }                                                                                    
5557                 }                                                                                        
5558             } else if (i instanceof LauncherAppWidgetInfo) {                                             
5559                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
5560                 ComponentName cn = info.providerName;                                                    
5561                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5562                     filtered.add(info);                                                                  
5563                 }                                                                                        
5564             }                                                                                            
5565         }                                                                                                
5566         return new ArrayList<ItemInfo>(filtered);                                                        
5567     }                                                                                                    
5568                                                                                                          
5569     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,                   
5570             final UserHandleCompat user) {                                                               
5571         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
5572             @Override                                                                                    
5573             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
5574                 if (info.user == null) {                                                                 
5575                     return cn.equals(cname);                                                             
5576                 } else {                                                                                 
5577                     return cn.equals(cname) && info.user.equals(user);                                   
5578                 }                                                                                        
5579             }                                                                                            
5580         };                                                                                               
5581         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
5582     }                                                                                                    
5583                                                                                                          
5584     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
5585         if (i instanceof ShortcutInfo) {                                                                 
5586             ShortcutInfo info = (ShortcutInfo) i;                                                        
5587             // We need to check for ACTION_MAIN otherwise getComponent() might                           
5588             // return null for some shortcuts (for instance, for shortcuts to                            
5589             // web pages.)                                                                               
5590             Intent intent = info.intent;                                                                 
5591             ComponentName name = intent.getComponent();                                                  
5592             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
5593                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
5594                 return true;                                                                             
5595             }                                                                                            
5596 <<<<<<< GitAnalyzerPlus_ours                                                                             
5597             // placeholder shortcuts get special treatment, let them through too.                        
5598             if (info.isPromise()) {                                                                      
5599                 return true;                                                                             
5600             }                                                                                            
5601 ||||||| GitAnalyzerPlus_base                                                                             
5602                 }                                                                                        
5603             }                                                                                            
5604         }                                                                                                
5605         // from the db                                                                                   
5606         if (info.title == null) {                                                                        
5607             if (c != null) {                                                                             
5608                 info.title =  c.getString(titleIndex);                                                   
5609             }                                                                                            
5610         }                                                                                                
5611         // fall back to the class name of the activity                                                   
5612         if (info.title == null) {                                                                        
5613             info.title = componentName.getClassName();                                                   
5614         }                                                                                                
5615         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
5616         return info;                                                                                     
5617     }                                                                                                    
5618                                                                                                          
5619     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
5620             ItemInfoFilter f) {                                                                          
5621         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
5622         for (ItemInfo i : infos) {                                                                       
5623             if (i instanceof ShortcutInfo) {                                                             
5624                 ShortcutInfo info = (ShortcutInfo) i;                                                    
5625                 ComponentName cn = info.intent.getComponent();                                           
5626                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5627                     filtered.add(info);                                                                  
5628                 }                                                                                        
5629             } else if (i instanceof FolderInfo) {                                                        
5630                 FolderInfo info = (FolderInfo) i;                                                        
5631                 for (ShortcutInfo s : info.contents) {                                                   
5632                     ComponentName cn = s.intent.getComponent();                                          
5633                     if (cn != null && f.filterItem(info, s, cn)) {                                       
5634                         filtered.add(s);                                                                 
5635                     }                                                                                    
5636                 }                                                                                        
5637             } else if (i instanceof LauncherAppWidgetInfo) {                                             
5638                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
5639                 ComponentName cn = info.providerName;                                                    
5640                 if (cn != null && f.filterItem(null, info, cn)) {                                        
5641                     filtered.add(info);                                                                  
5642                 }                                                                                        
5643             }                                                                                            
5644         }                                                                                                
5645         return new ArrayList<ItemInfo>(filtered);                                                        
5646     }                                                                                                    
5647                                                                                                          
5648     private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {                             
5649         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
5650             @Override                                                                                    
5651             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
5652                 return cn.getPackageName().equals(pn);                                                   
5653             }                                                                                            
5654         };                                                                                               
5655         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
5656     }                                                                                                    
5657                                                                                                          
5658     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {                 
5659         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
5660             @Override                                                                                    
5661             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
5662                 return cn.equals(cname);                                                                 
5663             }                                                                                            
5664         };                                                                                               
5665         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
5666     }                                                                                                    
5667                                                                                                          
5668     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
5669         if (i instanceof ShortcutInfo) {                                                                 
5670             ShortcutInfo info = (ShortcutInfo) i;                                                        
5671             // We need to check for ACTION_MAIN otherwise getComponent() might                           
5672             // return null for some shortcuts (for instance, for shortcuts to                            
5673             // web pages.)                                                                               
5674             Intent intent = info.intent;                                                                 
5675             ComponentName name = intent.getComponent();                                                  
5676             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
5677                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
5678                 return true;                                                                             
5679             }                                                                                            
5680             // placeholder shortcuts get special treatment, let them through too.                        
5681             if (info.getRestoredIntent() != null) {                                                      
5682                 return true;                                                                             
5683             }                                                                                            
5684         }                                                                                                
5685         return false;                                                                                    
5686     }                                                                                                    
5687                                                                                                          
5688     /**                                                                                                  
5689      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
5690      */                                                                                                  
5691     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
5692             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
5693             int titleIndex) {                                                                            
5694                                                                                                          
5695         Bitmap icon = null;                                                                              
5696         final ShortcutInfo info = new ShortcutInfo();                                                    
5697         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
5698                                                                                                          
5699         // TODO: If there's an explicit component and we can't install that, delete it.                  
5700                                                                                                          
5701         info.title = c.getString(titleIndex);                                                            
5702                                                                                                          
5703         int iconType = c.getInt(iconTypeIndex);                                                          
5704         switch (iconType) {                                                                              
5705         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
5706             String packageName = c.getString(iconPackageIndex);                                          
5707             String resourceName = c.getString(iconResourceIndex);                                        
5708             PackageManager packageManager = context.getPackageManager();                                 
5709             info.customIcon = false;                                                                     
5710             // the resource                                                                              
5711             try {                                                                                        
5712                 Resources resources = packageManager.getResourcesForApplication(packageName);            
5713                 if (resources != null) {                                                                 
5714                     final int id = resources.getIdentifier(resourceName, null, null);                    
5715                     icon = Utilities.createIconBitmap(                                                   
5716                             mIconCache.getFullResIcon(resources, id), context);                          
5717                 }                                                                                        
5718             } catch (Exception e) {                                                                      
5719                 // drop this.  we have other places to look for icons                                    
5720             }                                                                                            
5721             // the db                                                                                    
5722             if (icon == null) {                                                                          
5723                 icon = getIconFromCursor(c, iconIndex, context);                                         
5724             }                                                                                            
5725             // the fallback icon                                                                         
5726             if (icon == null) {                                                                          
5727                 icon = getFallbackIcon();                                                                
5728                 info.usingFallbackIcon = true;                                                           
5729             }                                                                                            
5730             break;                                                                                       
5731         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
5732             icon = getIconFromCursor(c, iconIndex, context);                                             
5733             if (icon == null) {                                                                          
5734                 icon = getFallbackIcon();                                                                
5735                 info.customIcon = false;                                                                 
5736                 info.usingFallbackIcon = true;                                                           
5737             } else {                                                                                     
5738                 info.customIcon = true;                                                                  
5739             }                                                                                            
5740             break;                                                                                       
5741         default:                                                                                         
5742             icon = getFallbackIcon();                                                                    
5743             info.usingFallbackIcon = true;                                                               
5744             info.customIcon = false;                                                                     
5745             break;                                                                                       
5746         }                                                                                                
5747         info.setIcon(icon);                                                                              
5748         return info;                                                                                     
5749     }                                                                                                    
5750                                                                                                          
5751     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
5752         @SuppressWarnings("all") // suppress dead code warning                                           
5753         final boolean debug = false;                                                                     
5754         if (debug) {                                                                                     
5755             Log.d(TAG, "getIconFromCursor app="                                                          
5756                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
5757         }                                                                                                
5758         byte[] data = c.getBlob(iconIndex);                                                              
5759         try {                                                                                            
5760             return Utilities.createIconBitmap(                                                           
5761                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
5762         } catch (Exception e) {                                                                          
5763             return null;                                                                                 
5764         }                                                                                                
5765     }                                                                                                    
5766                                                                                                          
5767     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
5768             int cellX, int cellY, boolean notify) {                                                      
5769         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
5770         if (info == null) {                                                                              
5771             return null;                                                                                 
5772         }                                                                                                
5773         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
5774                                                                                                          
5775         return info;                                                                                     
5776     }                                                                                                    
5777                                                                                                          
5778     /**                                                                                                  
5779      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
5780      */                                                                                                  
5781     AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                        
5782             ComponentName component) {                                                                   
5783         List<AppWidgetProviderInfo> widgets =                                                            
5784             AppWidgetManager.getInstance(context).getInstalledProviders();                               
5785         for (AppWidgetProviderInfo info : widgets) {                                                     
5786             if (info.provider.equals(component)) {                                                       
5787                 return info;                                                                             
5788             }                                                                                            
5789         }                                                                                                
5790         return null;                                                                                     
5791     }                                                                                                    
5792                                                                                                          
5793     /**                                                                                                  
5794      * Returns a list of all the widgets that can handle configuration with a particular mimeType.       
5795      */                                                                                                  
5796     List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {        
5797         final PackageManager packageManager = context.getPackageManager();                               
5798         final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =                         
5799             new ArrayList<WidgetMimeTypeHandlerData>();                                                  
5800                                                                                                          
5801         final Intent supportsIntent =                                                                    
5802             new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);                         
5803         supportsIntent.setType(mimeType);                                                                
5804                                                                                                          
5805         // Create a set of widget configuration components that we can test against                      
5806         final List<AppWidgetProviderInfo> widgets =                                                      
5807             AppWidgetManager.getInstance(context).getInstalledProviders();                               
5808         final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =             
5809             new HashMap<ComponentName, AppWidgetProviderInfo>();                                         
5810         for (AppWidgetProviderInfo info : widgets) {                                                     
5811             configurationComponentToWidget.put(info.configure, info);                                    
5812         }                                                                                                
5813                                                                                                          
5814         // Run through each of the intents that can handle this type of clip data, and cross             
5815         // reference them with the components that are actual configuration components                   
5816         final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,        
5817                 PackageManager.MATCH_DEFAULT_ONLY);                                                      
5818         for (ResolveInfo info : activities) {                                                            
5819             final ActivityInfo activityInfo = info.activityInfo;                                         
5820             final ComponentName infoComponent = new ComponentName(activityInfo.packageName,              
5821                     activityInfo.name);                                                                  
5822             if (configurationComponentToWidget.containsKey(infoComponent)) {                             
5823                 supportedConfigurationActivities.add(                                                    
5824                         new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,                        
5825                                 configurationComponentToWidget.get(infoComponent)));                     
5826             }                                                                                            
5827         }                                                                                                
5828         return supportedConfigurationActivities;                                                         
5829     }                                                                                                    
5830                                                                                                          
5831     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
5832         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
5833         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
5834         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
5835                                                                                                          
5836         if (intent == null) {                                                                            
5837             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
5838             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
5839             return null;                                                                                 
5840         }                                                                                                
5841                                                                                                          
5842         Bitmap icon = null;                                                                              
5843         boolean customIcon = false;                                                                      
5844         ShortcutIconResource iconResource = null;                                                        
5845                                                                                                          
5846         if (bitmap != null && bitmap instanceof Bitmap) {                                                
5847             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
5848             customIcon = true;                                                                           
5849         } else {                                                                                         
5850             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
5851             if (extra != null && extra instanceof ShortcutIconResource) {                                
5852                 try {                                                                                    
5853                     iconResource = (ShortcutIconResource) extra;                                         
5854                     final PackageManager packageManager = context.getPackageManager();                   
5855                     Resources resources = packageManager.getResourcesForApplication(                     
5856                             iconResource.packageName);                                                   
5857                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
5858                     icon = Utilities.createIconBitmap(                                                   
5859                             mIconCache.getFullResIcon(resources, id), context);                          
5860                 } catch (Exception e) {                                                                  
5861                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
5862                 }                                                                                        
5863             }                                                                                            
5864         }                                                                                                
5865                                                                                                          
5866         final ShortcutInfo info = new ShortcutInfo();                                                    
5867                                                                                                          
5868         if (icon == null) {                                                                              
5869             if (fallbackIcon != null) {                                                                  
5870                 icon = fallbackIcon;                                                                     
5871             } else {                                                                                     
5872                 icon = getFallbackIcon();                                                                
5873                 info.usingFallbackIcon = true;                                                           
5874             }                                                                                            
5875         }                                                                                                
5876         info.setIcon(icon);                                                                              
5877                                                                                                          
5878         info.title = name;                                                                               
5879         info.intent = intent;                                                                            
5880         info.customIcon = customIcon;                                                                    
5881         info.iconResource = iconResource;                                                                
5882                                                                                                          
5883         return info;                                                                                     
5884     }                                                                                                    
5885                                                                                                          
5886     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,             
5887             int iconIndex) {                                                                             
5888         // If apps can't be on SD, don't even bother.                                                    
5889         if (!mAppsCanBeOnRemoveableStorage) {                                                            
5890             return false;                                                                                
5891         }                                                                                                
5892         // If this icon doesn't have a custom icon, check to see                                         
5893         // what's stored in the DB, and if it doesn't match what                                         
5894         // we're going to show, store what we are going to show back                                     
5895         // into the DB.  We do this so when we're loading, if the                                        
5896         // package manager can't find an icon (for example because                                       
5897         // the app is on SD) then we can use that instead.                                               
5898         if (!info.customIcon && !info.usingFallbackIcon) {                                               
5899             cache.put(info, c.getBlob(iconIndex));                                                       
5900             return true;                                                                                 
5901         }                                                                                                
5902         return false;                                                                                    
5903     }                                                                                                    
5904     void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {                              
5905         boolean needSave = false;                                                                        
5906         try {                                                                                            
5907             if (data != null) {                                                                          
5908                 Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);                      
5909                 Bitmap loaded = info.getIcon(mIconCache);                                                
5910                 needSave = !saved.sameAs(loaded);                                                        
5911             } else {                                                                                     
5912                 needSave = true;                                                                         
5913             }                                                                                            
5914         } catch (Exception e) {                                                                          
5915             needSave = true;                                                                             
5916         }                                                                                                
5917         if (needSave) {                                                                                  
5918             Log.d(TAG, "going to save icon bitmap for info=" + info);                                    
5919             // This is slower than is ideal, but this only happens once                                  
5920             // or when the app is updated with a new icon.                                               
5921             updateItemInDatabase(context, info);                                                         
5922         }                                                                                                
5923     }                                                                                                    
5924                                                                                                          
5925     /**                                                                                                  
5926      * Return an existing FolderInfo object if we have encountered this ID previously,                   
5927      * or make a new one.                                                                                
5928      */                                                                                                  
5929     private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {             
5930         // See if a placeholder was created for us already                                               
5931         FolderInfo folderInfo = folders.get(id);                                                         
5932         if (folderInfo == null) {                                                                        
5933             // No placeholder -- create a new instance                                                   
5934             folderInfo = new FolderInfo();                                                               
5935             folders.put(id, folderInfo);                                                                 
5936         }                                                                                                
5937         return folderInfo;                                                                               
5938     }                                                                                                    
5939                                                                                                          
5940     public static final Comparator<AppInfo> getAppNameComparator() {                                     
5941         final Collator collator = Collator.getInstance();                                                
5942         return new Comparator<AppInfo>() {                                                               
5943             public final int compare(AppInfo a, AppInfo b) {                                             
5944                 int result = collator.compare(a.title.toString().trim(),                                 
5945                         b.title.toString().trim());                                                      
5946                 if (result == 0) {                                                                       
5947                     result = a.componentName.compareTo(b.componentName);                                 
5948                 }                                                                                        
5949                 return result;                                                                           
5950             }                                                                                            
5951         };                                                                                               
5952     }                                                                                                    
5953     public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR                                  
5954             = new Comparator<AppInfo>() {                                                                
5955         public final int compare(AppInfo a, AppInfo b) {                                                 
5956             if (a.firstInstallTime < b.firstInstallTime) return 1;                                       
5957             if (a.firstInstallTime > b.firstInstallTime) return -1;                                      
5958             return 0;                                                                                    
5959         }                                                                                                
5960     };                                                                                                   
5961     public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {                    
5962         final Collator collator = Collator.getInstance();                                                
5963         return new Comparator<AppWidgetProviderInfo>() {                                                 
5964             public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {                 
5965                 return collator.compare(a.label.toString().trim(), b.label.toString().trim());           
5966             }                                                                                            
5967         };                                                                                               
5968     }                                                                                                    
5969     static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {                             
5970         if (info.activityInfo != null) {                                                                 
5971             return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);             
5972         } else {                                                                                         
5973             return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);               
5974         }                                                                                                
5975     }                                                                                                    
5976     public static class ShortcutNameComparator implements Comparator<ResolveInfo> {                      
5977         private Collator mCollator;                                                                      
5978         private PackageManager mPackageManager;                                                          
5979         private HashMap<Object, CharSequence> mLabelCache;                                               
5980         ShortcutNameComparator(PackageManager pm) {                                                      
5981             mPackageManager = pm;                                                                        
5982             mLabelCache = new HashMap<Object, CharSequence>();                                           
5983             mCollator = Collator.getInstance();                                                          
5984         }                                                                                                
5985         ShortcutNameComparator(PackageManager pm, HashMap<Object, CharSequence> labelCache) {            
5986             mPackageManager = pm;                                                                        
5987             mLabelCache = labelCache;                                                                    
5988             mCollator = Collator.getInstance();                                                          
5989         }                                                                                                
5990         public final int compare(ResolveInfo a, ResolveInfo b) {                                         
5991             CharSequence labelA, labelB;                                                                 
5992             ComponentName keyA = LauncherModel.getComponentNameFromResolveInfo(a);                       
5993             ComponentName keyB = LauncherModel.getComponentNameFromResolveInfo(b);                       
5994             if (mLabelCache.containsKey(keyA)) {                                                         
5995                 labelA = mLabelCache.get(keyA);                                                          
5996             } else {                                                                                     
5997                 labelA = a.loadLabel(mPackageManager).toString().trim();                                 
5998                                                                                                          
5999                 mLabelCache.put(keyA, labelA);                                                           
6000             }                                                                                            
6001             if (mLabelCache.containsKey(keyB)) {                                                         
6002                 labelB = mLabelCache.get(keyB);                                                          
6003             } else {                                                                                     
6004                 labelB = b.loadLabel(mPackageManager).toString().trim();                                 
6005                                                                                                          
6006                 mLabelCache.put(keyB, labelB);                                                           
6007             }                                                                                            
6008             return mCollator.compare(labelA, labelB);                                                    
6009         }                                                                                                
6010     };                                                                                                   
6011     public static class WidgetAndShortcutNameComparator implements Comparator<Object> {                  
6012         private Collator mCollator;                                                                      
6013         private PackageManager mPackageManager;                                                          
6014         private HashMap<Object, String> mLabelCache;                                                     
6015         WidgetAndShortcutNameComparator(PackageManager pm) {                                             
6016             mPackageManager = pm;                                                                        
6017             mLabelCache = new HashMap<Object, String>();                                                 
6018             mCollator = Collator.getInstance();                                                          
6019         }                                                                                                
6020         public final int compare(Object a, Object b) {                                                   
6021             String labelA, labelB;                                                                       
6022             if (mLabelCache.containsKey(a)) {                                                            
6023                 labelA = mLabelCache.get(a);                                                             
6024             } else {                                                                                     
6025                 labelA = (a instanceof AppWidgetProviderInfo) ?                                          
6026                     ((AppWidgetProviderInfo) a).label :                                                  
6027                     ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();                      
6028                 mLabelCache.put(a, labelA);                                                              
6029             }                                                                                            
6030             if (mLabelCache.containsKey(b)) {                                                            
6031                 labelB = mLabelCache.get(b);                                                             
6032             } else {                                                                                     
6033                 labelB = (b instanceof AppWidgetProviderInfo) ?                                          
6034                     ((AppWidgetProviderInfo) b).label :                                                  
6035                     ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();                      
6036                 mLabelCache.put(b, labelB);                                                              
6037             }                                                                                            
6038             return mCollator.compare(labelA, labelB);                                                    
6039         }                                                                                                
6040     };                                                                                                   
6041 =======                                                                                                  
6042 >>>>>>> GitAnalyzerPlus_theirs                                                                           
6043         }                                                                                                
6044         return false;                                                                                    
6045     }                                                                                                    
6046                                                                                                          
6047     /**                                                                                                  
6048      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
6049      */                                                                                                  
6050     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
6051             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
6052             int titleIndex) {                                                                            
6053                                                                                                          
6054         Bitmap icon = null;                                                                              
6055         final ShortcutInfo info = new ShortcutInfo();                                                    
6056         // Non-app shortcuts are only supported for current user.                                        
6057         info.user = UserHandleCompat.myUserHandle();                                                     
6058         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
6059                                                                                                          
6060         // TODO: If there's an explicit component and we can't install that, delete it.                  
6061                                                                                                          
6062         info.title = c.getString(titleIndex);                                                            
6063                                                                                                          
6064         int iconType = c.getInt(iconTypeIndex);                                                          
6065         switch (iconType) {                                                                              
6066         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
6067             String packageName = c.getString(iconPackageIndex);                                          
6068             String resourceName = c.getString(iconResourceIndex);                                        
6069             PackageManager packageManager = context.getPackageManager();                                 
6070             info.customIcon = false;                                                                     
6071             // the resource                                                                              
6072             try {                                                                                        
6073                 Resources resources = packageManager.getResourcesForApplication(packageName);            
6074                 if (resources != null) {                                                                 
6075                     final int id = resources.getIdentifier(resourceName, null, null);                    
6076                     icon = Utilities.createIconBitmap(                                                   
6077                             mIconCache.getFullResIcon(resources, id), context);                          
6078                 }                                                                                        
6079             } catch (Exception e) {                                                                      
6080                 // drop this.  we have other places to look for icons                                    
6081             }                                                                                            
6082             // the db                                                                                    
6083             if (icon == null) {                                                                          
6084                 icon = getIconFromCursor(c, iconIndex, context);                                         
6085             }                                                                                            
6086             // the fallback icon                                                                         
6087             if (icon == null) {                                                                          
6088                 icon = mIconCache.getDefaultIcon(info.user);                                             
6089                 info.usingFallbackIcon = true;                                                           
6090             }                                                                                            
6091             break;                                                                                       
6092         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
6093             icon = getIconFromCursor(c, iconIndex, context);                                             
6094             if (icon == null) {                                                                          
6095                 icon = mIconCache.getDefaultIcon(info.user);                                             
6096                 info.customIcon = false;                                                                 
6097                 info.usingFallbackIcon = true;                                                           
6098             } else {                                                                                     
6099                 info.customIcon = true;                                                                  
6100             }                                                                                            
6101             break;                                                                                       
6102         default:                                                                                         
6103             icon = mIconCache.getDefaultIcon(info.user);                                                 
6104             info.usingFallbackIcon = true;                                                               
6105             info.customIcon = false;                                                                     
6106             break;                                                                                       
6107         }                                                                                                
6108         info.setIcon(icon);                                                                              
6109         return info;                                                                                     
6110     }                                                                                                    
6111                                                                                                          
6112     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
6113         @SuppressWarnings("all") // suppress dead code warning                                           
6114         final boolean debug = false;                                                                     
6115         if (debug) {                                                                                     
6116             Log.d(TAG, "getIconFromCursor app="                                                          
6117                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
6118         }                                                                                                
6119         byte[] data = c.getBlob(iconIndex);                                                              
6120         try {                                                                                            
6121             return Utilities.createIconBitmap(                                                           
6122                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
6123         } catch (Exception e) {                                                                          
6124             return null;                                                                                 
6125         }                                                                                                
6126     }                                                                                                    
6127                                                                                                          
6128     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
6129             int cellX, int cellY, boolean notify) {                                                      
6130         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
6131         if (info == null) {                                                                              
6132             return null;                                                                                 
6133         }                                                                                                
6134         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
6135                                                                                                          
6136         return info;                                                                                     
6137     }                                                                                                    
6138                                                                                                          
6139     /**                                                                                                  
6140      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
6141      */                                                                                                  
6142     static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                 
6143             ComponentName component) {                                                                   
6144         List<AppWidgetProviderInfo> widgets =                                                            
6145             AppWidgetManager.getInstance(context).getInstalledProviders();                               
6146         for (AppWidgetProviderInfo info : widgets) {                                                     
6147             if (info.provider.equals(component)) {                                                       
6148                 return info;                                                                             
6149             }                                                                                            
6150         }                                                                                                
6151         return null;                                                                                     
6152     }                                                                                                    
6153                                                                                                          
6154     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
6155         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
6156         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
6157         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
6158                                                                                                          
6159         if (intent == null) {                                                                            
6160             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
6161             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
6162             return null;                                                                                 
6163         }                                                                                                
6164                                                                                                          
6165         Bitmap icon = null;                                                                              
6166         boolean customIcon = false;                                                                      
6167         ShortcutIconResource iconResource = null;                                                        
6168                                                                                                          
6169         if (bitmap != null && bitmap instanceof Bitmap) {                                                
6170             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
6171             customIcon = true;                                                                           
6172         } else {                                                                                         
6173             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
6174             if (extra != null && extra instanceof ShortcutIconResource) {                                
6175                 try {                                                                                    
6176                     iconResource = (ShortcutIconResource) extra;                                         
6177                     final PackageManager packageManager = context.getPackageManager();                   
6178                     Resources resources = packageManager.getResourcesForApplication(                     
6179                             iconResource.packageName);                                                   
6180                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
6181                     icon = Utilities.createIconBitmap(                                                   
6182                             mIconCache.getFullResIcon(resources, id),                                    
6183                             context);                                                                    
6184                 } catch (Exception e) {                                                                  
6185                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
6186                 }                                                                                        
6187             }                                                                                            
6188         }                                                                                                
6189                                                                                                          
6190         final ShortcutInfo info = new ShortcutInfo();                                                    
6191                                                                                                          
6192         // Only support intents for current user for now. Intents sent from other                        
6193         // users wouldn't get here without intent forwarding anyway.                                     
6194         info.user = UserHandleCompat.myUserHandle();                                                     
6195         if (icon == null) {                                                                              
6196             if (fallbackIcon != null) {                                                                  
6197                 icon = fallbackIcon;                                                                     
6198             } else {                                                                                     
6199                 icon = mIconCache.getDefaultIcon(info.user);                                             
6200                 info.usingFallbackIcon = true;                                                           
6201             }                                                                                            
6202         }                                                                                                
6203         info.setIcon(icon);                                                                              
6204                                                                                                          
6205         info.title = name;                                                                               
6206         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
6207                 info.title.toString(), info.user);                                                       
6208         info.intent = intent;                                                                            
6209         info.customIcon = customIcon;                                                                    
6210         info.iconResource = iconResource;                                                                
6211                                                                                                          
6212         return info;                                                                                     
6213     }                                                                                                    
6214                                                                                                          
6215     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,             
6216             int iconIndex) {                                                                             
6217         // If apps can't be on SD, don't even bother.                                                    
6218         if (!mAppsCanBeOnRemoveableStorage) {                                                            
6219             return false;                                                                                
6220         }                                                                                                
6221         // If this icon doesn't have a custom icon, check to see                                         
6222         // what's stored in the DB, and if it doesn't match what                                         
6223         // we're going to show, store what we are going to show back                                     
6224         // into the DB.  We do this so when we're loading, if the                                        
6225         // package manager can't find an icon (for example because                                       
6226         // the app is on SD) then we can use that instead.                                               
6227         if (!info.customIcon && !info.usingFallbackIcon) {                                               
6228             cache.put(info, c.getBlob(iconIndex));                                                       
6229             return true;                                                                                 
6230         }                                                                                                
6231         return false;                                                                                    
6232     }                                                                                                    
6233     void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {                              
6234         boolean needSave = false;                                                                        
6235         try {                                                                                            
6236             if (data != null) {                                                                          
6237                 Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);                      
6238                 Bitmap loaded = info.getIcon(mIconCache);                                                
6239                 needSave = !saved.sameAs(loaded);                                                        
6240             } else {                                                                                     
6241                 needSave = true;                                                                         
6242             }                                                                                            
6243         } catch (Exception e) {                                                                          
6244             needSave = true;                                                                             
6245         }                                                                                                
6246         if (needSave) {                                                                                  
6247             Log.d(TAG, "going to save icon bitmap for info=" + info);                                    
6248             // This is slower than is ideal, but this only happens once                                  
6249             // or when the app is updated with a new icon.                                               
6250             updateItemInDatabase(context, info);                                                         
6251         }                                                                                                
6252     }                                                                                                    
6253                                                                                                          
6254     /**                                                                                                  
6255      * Return an existing FolderInfo object if we have encountered this ID previously,                   
6256      * or make a new one.                                                                                
6257      */                                                                                                  
6258     private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {             
6259         // See if a placeholder was created for us already                                               
6260         FolderInfo folderInfo = folders.get(id);                                                         
6261         if (folderInfo == null) {                                                                        
6262             // No placeholder -- create a new instance                                                   
6263             folderInfo = new FolderInfo();                                                               
6264             folders.put(id, folderInfo);                                                                 
6265         }                                                                                                
6266         return folderInfo;                                                                               
6267     }                                                                                                    
6268                                                                                                          
6269     public static final Comparator<AppInfo> getAppNameComparator() {                                     
6270         final Collator collator = Collator.getInstance();                                                
6271         return new Comparator<AppInfo>() {                                                               
6272             public final int compare(AppInfo a, AppInfo b) {                                             
6273                 if (a.user.equals(b.user)) {                                                             
6274                     int result = collator.compare(a.title.toString().trim(),                             
6275                             b.title.toString().trim());                                                  
6276                     if (result == 0) {                                                                   
6277                         result = a.componentName.compareTo(b.componentName);                             
6278                     }                                                                                    
6279                     return result;                                                                       
6280                 } else {                                                                                 
6281                     // TODO Need to figure out rules for sorting                                         
6282                     // profiles, this puts work second.                                                  
6283                     return a.user.toString().compareTo(b.user.toString());                               
6284                 }                                                                                        
6285             }                                                                                            
6286         };                                                                                               
6287     }                                                                                                    
6288     public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR                                  
6289             = new Comparator<AppInfo>() {                                                                
6290         public final int compare(AppInfo a, AppInfo b) {                                                 
6291             if (a.firstInstallTime < b.firstInstallTime) return 1;                                       
6292             if (a.firstInstallTime > b.firstInstallTime) return -1;                                      
6293             return 0;                                                                                    
6294         }                                                                                                
6295     };                                                                                                   
6296     static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {                             
6297         if (info.activityInfo != null) {                                                                 
6298             return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);             
6299         } else {                                                                                         
6300             return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);               
6301         }                                                                                                
6302     }                                                                                                    
6303     public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {       
6304         private Collator mCollator;                                                                      
6305         private HashMap<Object, CharSequence> mLabelCache;                                               
6306         ShortcutNameComparator(PackageManager pm) {                                                      
6307             mLabelCache = new HashMap<Object, CharSequence>();                                           
6308             mCollator = Collator.getInstance();                                                          
6309         }                                                                                                
6310         ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {                               
6311             mLabelCache = labelCache;                                                                    
6312             mCollator = Collator.getInstance();                                                          
6313         }                                                                                                
6314         public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {           
6315             String labelA, labelB;                                                                       
6316             ComponentName keyA = a.getComponentName();                                                   
6317             ComponentName keyB = b.getComponentName();                                                   
6318             if (mLabelCache.containsKey(keyA)) {                                                         
6319                 labelA = mLabelCache.get(keyA).toString();                                               
6320             } else {                                                                                     
6321                 labelA = a.getLabel().toString().trim();                                                 
6322                                                                                                          
6323                 mLabelCache.put(keyA, labelA);                                                           
6324             }                                                                                            
6325             if (mLabelCache.containsKey(keyB)) {                                                         
6326                 labelB = mLabelCache.get(keyB).toString();                                               
6327             } else {                                                                                     
6328                 labelB = b.getLabel().toString().trim();                                                 
6329                                                                                                          
6330                 mLabelCache.put(keyB, labelB);                                                           
6331             }                                                                                            
6332             return mCollator.compare(labelA, labelB);                                                    
6333         }                                                                                                
6334     };                                                                                                   
6335     public static class WidgetAndShortcutNameComparator implements Comparator<Object> {                  
6336         private final AppWidgetManagerCompat mManager;                                                   
6337         private final PackageManager mPackageManager;                                                    
6338         private final HashMap<Object, String> mLabelCache;                                               
6339         private final Collator mCollator;                                                                
6340                                                                                                          
6341         WidgetAndShortcutNameComparator(Context context) {                                               
6342             mManager = AppWidgetManagerCompat.getInstance(context);                                      
6343             mPackageManager = context.getPackageManager();                                               
6344             mLabelCache = new HashMap<Object, String>();                                                 
6345             mCollator = Collator.getInstance();                                                          
6346         }                                                                                                
6347         public final int compare(Object a, Object b) {                                                   
6348             String labelA, labelB;                                                                       
6349             if (mLabelCache.containsKey(a)) {                                                            
6350                 labelA = mLabelCache.get(a);                                                             
6351             } else {                                                                                     
6352                 labelA = (a instanceof AppWidgetProviderInfo)                                            
6353                         ? mManager.loadLabel((AppWidgetProviderInfo) a)                                  
6354                         : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();                
6355                 mLabelCache.put(a, labelA);                                                              
6356             }                                                                                            
6357             if (mLabelCache.containsKey(b)) {                                                            
6358                 labelB = mLabelCache.get(b);                                                             
6359             } else {                                                                                     
6360                 labelB = (b instanceof AppWidgetProviderInfo)                                            
6361                         ? mManager.loadLabel((AppWidgetProviderInfo) b)                                  
6362                         : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();                
6363                 mLabelCache.put(b, labelB);                                                              
6364             }                                                                                            
6365             return mCollator.compare(labelA, labelB);                                                    
6366         }                                                                                                
6367     };                                                                                                   
6368                                                                                                          
6369     static boolean isValidProvider(AppWidgetProviderInfo provider) {                                     
6370         return (provider != null) && (provider.provider != null)                                         
6371                 && (provider.provider.getPackageName() != null);                                         
6372     }                                                                                                    
6373                                                                                                          
6374     public void dumpState() {                                                                            
6375         Log.d(TAG, "mCallbacks=" + mCallbacks);                                                          
6376         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);                  
6377         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);                
6378         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);            
6379         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);          
6380         if (mLoaderTask != null) {                                                                       
6381             mLoaderTask.dumpState();                                                                     
6382         } else {                                                                                         
6383             Log.d(TAG, "mLoaderTask=null");                                                              
6384         }                                                                                                
6385     }                                                                                                    
6386 }                                                                                                        
   1 /*                                                                                                       
   2  * Copyright (C) 2008 The Android Open Source Project                                                    
   3  *                                                                                                       
   4  * Licensed under the Apache License, Version 2.0 (the "License");                                       
   5  * you may not use this file except in compliance with the License.                                      
   6  * You may obtain a copy of the License at                                                               
   7  *                                                                                                       
   8  *      http://www.apache.org/licenses/LICENSE-2.0                                                       
   9  *                                                                                                       
  10  * Unless required by applicable law or agreed to in writing, software                                   
  11  * distributed under the License is distributed on an "AS IS" BASIS,                                     
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                              
  13  * See the License for the specific language governing permissions and                                   
  14  * limitations under the License.                                                                        
  15  */                                                                                                      
  16                                                                                                          
  17 package com.android.launcher3;                                                                           
  18                                                                                                          
  19 import android.app.SearchManager;                                                                        
  20 import android.appwidget.AppWidgetManager;                                                               
  21 import android.appwidget.AppWidgetProviderInfo;                                                          
  22 import android.content.BroadcastReceiver;                                                                
  23 import android.content.ComponentName;                                                                    
  24 import android.content.ContentProviderClient;                                                            
  25 import android.content.ContentProviderOperation;                                                         
  26 import android.content.ContentResolver;                                                                  
  27 import android.content.ContentValues;                                                                    
  28 import android.content.Context;                                                                          
  29 import android.content.Intent;                                                                           
  30 import android.content.Intent.ShortcutIconResource;                                                      
  31 import android.content.IntentFilter;                                                                     
  32 import android.content.SharedPreferences;                                                                
  33 import android.content.pm.PackageManager;                                                                
  34 import android.content.pm.ProviderInfo;                                                                  
  35 import android.content.pm.ResolveInfo;                                                                   
  36 import android.content.res.Configuration;                                                                
  37 import android.content.res.Resources;                                                                    
  38 import android.database.Cursor;                                                                          
  39 import android.graphics.Bitmap;                                                                          
  40 import android.graphics.BitmapFactory;                                                                   
  41 import android.net.Uri;                                                                                  
  42 import android.os.Environment;                                                                           
  43 import android.os.Handler;                                                                               
  44 import android.os.HandlerThread;                                                                         
  45 import android.os.Parcelable;                                                                            
  46 import android.os.Process;                                                                               
  47 import android.os.RemoteException;                                                                       
  48 import android.os.SystemClock;                                                                           
  49 import android.provider.BaseColumns;                                                                     
  50 import android.text.TextUtils;                                                                           
  51 import android.util.Log;                                                                                 
  52 import android.util.Pair;                                                                                
  53                                                                                                          
  54 import com.android.launcher3.compat.AppWidgetManagerCompat;                                              
  55 import com.android.launcher3.compat.LauncherActivityInfoCompat;                                          
  56 import com.android.launcher3.compat.LauncherAppsCompat;                                                  
  57 import com.android.launcher3.compat.PackageInstallerCompat;                                              
  58 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;                           
  59 import com.android.launcher3.compat.UserHandleCompat;                                                    
  60 import com.android.launcher3.compat.UserManagerCompat;                                                   
  61                                                                                                          
  62 import java.lang.ref.WeakReference;                                                                      
  63 import java.net.URISyntaxException;                                                                      
  64 import java.security.InvalidParameterException;                                                          
  65 import java.text.Collator;                                                                               
  66 import java.util.ArrayList;                                                                              
  67 import java.util.Arrays;                                                                                 
  68 import java.util.Collection;                                                                             
  69 import java.util.Collections;                                                                            
  70 import java.util.Comparator;                                                                             
  71 import java.util.HashMap;                                                                                
  72 import java.util.HashSet;                                                                                
  73 import java.util.Iterator;                                                                               
  74 import java.util.List;                                                                                   
  75 import java.util.Map.Entry;                                                                              
  76 import java.util.Set;                                                                                    
  77 import java.util.TreeMap;                                                                                
  78 import java.util.concurrent.atomic.AtomicBoolean;                                                        
  79                                                                                                          
  80 /**                                                                                                      
  81  * Maintains in-memory state of the Launcher. It is expected that there should be only one               
  82  * LauncherModel object held in a static. Also provide APIs for updating the database state              
  83  * for the Launcher.                                                                                     
  84  */                                                                                                      
  85 public class LauncherModel extends BroadcastReceiver                                                     
  86         implements LauncherAppsCompat.OnAppsChangedCallbackCompat {                                      
  87     static final boolean DEBUG_LOADERS = false;                                                          
  88     private static final boolean DEBUG_RECEIVER = false;                                                 
  89     private static final boolean REMOVE_UNRESTORED_ICONS = true;                                         
  90                                                                                                          
  91     static final String TAG = "Launcher.Model";                                                          
  92                                                                                                          
  93     // true = use a "More Apps" folder for non-workspace apps on upgrade                                 
  94     // false = strew non-workspace apps across the workspace on upgrade                                  
  95     public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;                                    
  96     public static final int LOADER_FLAG_NONE = 0;                                                        
  97     public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;                                        
  98     public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;                                      
  99                                                                                                          
 100     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons                      
 101     private static final long INVALID_SCREEN_ID = -1L;                                                   
 102                                                                                                          
 103     private final boolean mAppsCanBeOnRemoveableStorage;                                                 
 104     private final boolean mOldContentProviderExists;                                                     
 105                                                                                                          
 106     private final LauncherAppState mApp;                                                                 
 107     private final Object mLock = new Object();                                                           
 108     private DeferredHandler mHandler = new DeferredHandler();                                            
 109     private LoaderTask mLoaderTask;                                                                      
 110     private boolean mIsLoaderTaskRunning;                                                                
 111     private volatile boolean mFlushingWorkerThread;                                                      
 112                                                                                                          
 113     // Specific runnable types that are run on the main thread deferred handler, this allows us to       
 114     // clear all queued binding runnables when the Launcher activity is destroyed.                       
 115     private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;                                            
 116     private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;                                           
 117                                                                                                          
 118     private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";                    
 119                                                                                                          
 120     private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");             
 121     static {                                                                                             
 122         sWorkerThread.start();                                                                           
 123     }                                                                                                    
 124     private static final Handler sWorker = new Handler(sWorkerThread.getLooper());                       
 125                                                                                                          
 126     // We start off with everything not loaded.  After that, we assume that                              
 127     // our monitoring of the package manager provides all updates and we never                           
 128     // need to do a requery.  These are only ever touched from the loader thread.                        
 129     private boolean mWorkspaceLoaded;                                                                    
 130     private boolean mAllAppsLoaded;                                                                      
 131                                                                                                          
 132     // When we are loading pages synchronously, we can't just post the binding of items on the side      
 133     // pages as this delays the rotation process.  Instead, we wait for a callback from the first        
 134     // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start       
 135     // a normal load, we also clear this set of Runnables.                                               
 136     static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();                 
 137                                                                                                          
 138     private WeakReference<Callbacks> mCallbacks;                                                         
 139                                                                                                          
 140     // < only access in worker thread >                                                                  
 141     AllAppsList mBgAllAppsList;                                                                          
 142                                                                                                          
 143     // The lock that must be acquired before referencing any static bg data structures.  Unlike          
 144     // other locks, this one can generally be held long-term because we never expect any of these        
 145     // static data structures to be referenced outside of the worker thread except on the first          
 146     // load after configuration change.                                                                  
 147     static final Object sBgLock = new Object();                                                          
 148                                                                                                          
 149     // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by               
 150     // LauncherModel to their ids                                                                        
 151     static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();                  
 152                                                                                                          
 153     // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts       
 154     //       created by LauncherModel that are directly on the home screen (however, no widgets or       
 155     //       shortcuts within folders).                                                                  
 156     static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();                      
 157                                                                                                          
 158     // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()    
 159     static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =                                        
 160         new ArrayList<LauncherAppWidgetInfo>();                                                          
 161                                                                                                          
 162     // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()                   
 163     static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();                 
 164                                                                                                          
 165     // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database      
 166     static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();                 
 167                                                                                                          
 168     // sBgWorkspaceScreens is the ordered set of workspace screens.                                      
 169     static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();                            
 170                                                                                                          
 171     // sPendingPackages is a set of packages which could be on sdcard and are not available yet          
 172     static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =                           
 173             new HashMap<UserHandleCompat, HashSet<String>>();                                            
 174                                                                                                          
 175     // </ only access in worker thread >                                                                 
 176                                                                                                          
 177     private IconCache mIconCache;                                                                        
 178                                                                                                          
 179     protected int mPreviousConfigMcc;                                                                    
 180                                                                                                          
 181     private final LauncherAppsCompat mLauncherApps;                                                      
 182     private final UserManagerCompat mUserManager;                                                        
 183                                                                                                          
 184     public interface Callbacks {                                                                         
 185         public boolean setLoadOnResume();                                                                
 186         public int getCurrentWorkspaceScreen();                                                          
 187         public void startBinding();                                                                      
 188         public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,                         
 189                               boolean forceAnimateIcons);                                                
 190         public void bindScreens(ArrayList<Long> orderedScreenIds);                                       
 191         public void bindAddScreens(ArrayList<Long> orderedScreenIds);                                    
 192         public void bindFolders(HashMap<Long,FolderInfo> folders);                                       
 193         public void finishBindingItems(boolean upgradePath);                                             
 194         public void bindAppWidget(LauncherAppWidgetInfo info);                                           
 195         public void bindAllApplications(ArrayList<AppInfo> apps);                                        
 196         public void bindAppsAdded(ArrayList<Long> newScreens,                                            
 197                                   ArrayList<ItemInfo> addNotAnimated,                                    
 198                                   ArrayList<ItemInfo> addAnimated,                                       
 199                                   ArrayList<AppInfo> addedApps);                                         
 200         public void bindAppsUpdated(ArrayList<AppInfo> apps);                                            
 201         public void bindAppsRestored(ArrayList<AppInfo> apps);                                           
 202         public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);                       
 203         public void updatePackageBadge(String packageName);                                              
 204         public void bindComponentsRemoved(ArrayList<String> packageNames,                                
 205                         ArrayList<AppInfo> appInfos, UserHandleCompat user);                             
 206         public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);                          
 207         public void bindSearchablesChanged();                                                            
 208         public boolean isAllAppsButtonRank(int rank);                                                    
 209         public void onPageBoundSynchronously(int page);                                                  
 210         public void dumpLogsToLocalData();                                                               
 211     }                                                                                                    
 212                                                                                                          
 213     public interface ItemInfoFilter {                                                                    
 214         public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);                     
 215     }                                                                                                    
 216                                                                                                          
 217     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {                      
 218         Context context = app.getContext();                                                              
 219                                                                                                          
 220         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();                        
 221         String oldProvider = context.getString(R.string.old_launcher_provider_uri);                      
 222         // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different               
 223         // resource string.                                                                              
 224         String redirectAuthority = Uri.parse(oldProvider).getAuthority();                                
 225         ProviderInfo providerInfo =                                                                      
 226                 context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY, 0);                
 227         ProviderInfo redirectProvider =                                                                  
 228                 context.getPackageManager().resolveContentProvider(redirectAuthority, 0);                
 229                                                                                                          
 230         Log.d(TAG, "Old launcher provider: " + oldProvider);                                             
 231         mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);                
 232                                                                                                          
 233         if (mOldContentProviderExists) {                                                                 
 234             Log.d(TAG, "Old launcher provider exists.");                                                 
 235         } else {                                                                                         
 236             Log.d(TAG, "Old launcher provider does not exist.");                                         
 237         }                                                                                                
 238                                                                                                          
 239         mApp = app;                                                                                      
 240         mBgAllAppsList = new AllAppsList(iconCache, appFilter);                                          
 241         mIconCache = iconCache;                                                                          
 242                                                                                                          
 243         final Resources res = context.getResources();                                                    
 244         Configuration config = res.getConfiguration();                                                   
 245         mPreviousConfigMcc = config.mcc;                                                                 
 246         mLauncherApps = LauncherAppsCompat.getInstance(context);                                         
 247         mUserManager = UserManagerCompat.getInstance(context);                                           
 248     }                                                                                                    
 249                                                                                                          
 250     /** Runs the specified runnable immediately if called from the main thread, otherwise it is          
 251      * posted on the main thread handler. */                                                             
 252     private void runOnMainThread(Runnable r) {                                                           
 253         runOnMainThread(r, 0);                                                                           
 254     }                                                                                                    
 255     private void runOnMainThread(Runnable r, int type) {                                                 
 256         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 257             // If we are on the worker thread, post onto the main handler                                
 258             mHandler.post(r);                                                                            
 259         } else {                                                                                         
 260             r.run();                                                                                     
 261         }                                                                                                
 262     }                                                                                                    
 263                                                                                                          
 264     /** Runs the specified runnable immediately if called from the worker thread, otherwise it is        
 265      * posted on the worker thread handler. */                                                           
 266     private static void runOnWorkerThread(Runnable r) {                                                  
 267         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 268             r.run();                                                                                     
 269         } else {                                                                                         
 270             // If we are not on the worker thread, then post to the worker handler                       
 271             sWorker.post(r);                                                                             
 272         }                                                                                                
 273     }                                                                                                    
 274                                                                                                          
 275     boolean canMigrateFromOldLauncherDb(Launcher launcher) {                                             
 276         return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;                         
 277     }                                                                                                    
 278                                                                                                          
 279     static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,               
 280                                  long screen) {                                                          
 281         LauncherAppState app = LauncherAppState.getInstance();                                           
 282         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                    
 283         final int xCount = (int) grid.numColumns;                                                        
 284         final int yCount = (int) grid.numRows;                                                           
 285         boolean[][] occupied = new boolean[xCount][yCount];                                              
 286                                                                                                          
 287         int cellX, cellY, spanX, spanY;                                                                  
 288         for (int i = 0; i < items.size(); ++i) {                                                         
 289             final ItemInfo item = items.get(i);                                                          
 290             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                        
 291                 if (item.screenId == screen) {                                                           
 292                     cellX = item.cellX;                                                                  
 293                     cellY = item.cellY;                                                                  
 294                     spanX = item.spanX;                                                                  
 295                     spanY = item.spanY;                                                                  
 296                     for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) {                
 297                         for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) {            
 298                             occupied[x][y] = true;                                                       
 299                         }                                                                                
 300                     }                                                                                    
 301                 }                                                                                        
 302             }                                                                                            
 303         }                                                                                                
 304                                                                                                          
 305         return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);                            
 306     }                                                                                                    
 307     static Pair<Long, int[]> findNextAvailableIconSpace(Context context, String name,                    
 308                                                         Intent launchIntent,                             
 309                                                         int firstScreenIndex,                            
 310                                                         ArrayList<Long> workspaceScreens) {              
 311         // Lock on the app so that we don't try and get the items while apps are being added             
 312         LauncherAppState app = LauncherAppState.getInstance();                                           
 313         LauncherModel model = app.getModel();                                                            
 314         boolean found = false;                                                                           
 315         synchronized (app) {                                                                             
 316             if (sWorkerThread.getThreadId() != Process.myTid()) {                                        
 317                 // Flush the LauncherModel worker thread, so that if we just did another                 
 318                 // processInstallShortcut, we give it time for its shortcut to get added to the          
 319                 // database (getItemsInLocalCoordinates reads the database)                              
 320                 model.flushWorkerThread();                                                               
 321             }                                                                                            
 322             final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);         
 323                                                                                                          
 324             // Try adding to the workspace screens incrementally, starting at the default or center      
 325             // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))       
 326             firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size());                      
 327             int count = workspaceScreens.size();                                                         
 328             for (int screen = firstScreenIndex; screen < count && !found; screen++) {                    
 329                 int[] tmpCoordinates = new int[2];                                                       
 330                 if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates,                            
 331                         workspaceScreens.get(screen))) {                                                 
 332                     // Update the Launcher db                                                            
 333                     return new Pair<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);          
 334                 }                                                                                        
 335             }                                                                                            
 336         }                                                                                                
 337         return null;                                                                                     
 338     }                                                                                                    
 339                                                                                                          
 340     public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {                       
 341         // Process the updated package state                                                             
 342         Runnable r = new Runnable() {                                                                    
 343             public void run() {                                                                          
 344                 Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                      
 345                 if (callbacks != null) {                                                                 
 346                     callbacks.updatePackageState(installInfo);                                           
 347                 }                                                                                        
 348             }                                                                                            
 349         };                                                                                               
 350         mHandler.post(r);                                                                                
 351     }                                                                                                    
 352                                                                                                          
 353     public void updatePackageBadge(final String packageName) {                                           
 354         // Process the updated package badge                                                             
 355         Runnable r = new Runnable() {                                                                    
 356             public void run() {                                                                          
 357                 Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                      
 358                 if (callbacks != null) {                                                                 
 359                     callbacks.updatePackageBadge(packageName);                                           
 360                 }                                                                                        
 361             }                                                                                            
 362         };                                                                                               
 363         mHandler.post(r);                                                                                
 364     }                                                                                                    
 365                                                                                                          
 366     public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {              
 367         final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                        
 368                                                                                                          
 369         if (allAppsApps == null) {                                                                       
 370             throw new RuntimeException("allAppsApps must not be null");                                  
 371         }                                                                                                
 372         if (allAppsApps.isEmpty()) {                                                                     
 373             return;                                                                                      
 374         }                                                                                                
 375                                                                                                          
 376         final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                           
 377         Iterator<AppInfo> iter = allAppsApps.iterator();                                                 
 378         while (iter.hasNext()) {                                                                         
 379             ItemInfo a = iter.next();                                                                    
 380             if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {                               
 381                 restoredAppsFinal.add((AppInfo) a);                                                      
 382             }                                                                                            
 383         }                                                                                                
 384                                                                                                          
 385         // Process the newly added applications and add them to the database first                       
 386         Runnable r = new Runnable() {                                                                    
 387             public void run() {                                                                          
 388                 runOnMainThread(new Runnable() {                                                         
 389                     public void run() {                                                                  
 390                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
 391                         if (callbacks == cb && cb != null) {                                             
 392                             if (!restoredAppsFinal.isEmpty()) {                                          
 393                                 for (AppInfo info : restoredAppsFinal) {                                 
 394                                     final Intent intent = info.getIntent();                              
 395                                     if (intent != null) {                                                
 396                                         mIconCache.deletePreloadedIcon(intent.getComponent(),            
 397                                                 info.user);                                              
 398                                     }                                                                    
 399                                 }                                                                        
 400                                 callbacks.bindAppsUpdated(restoredAppsFinal);                            
 401                             }                                                                            
 402                             callbacks.bindAppsAdded(null, null, null, allAppsApps);                      
 403                         }                                                                                
 404                     }                                                                                    
 405                 });                                                                                      
 406             }                                                                                            
 407         };                                                                                               
 408         runOnWorkerThread(r);                                                                            
 409     }                                                                                                    
 410                                                                                                          
 411     public void addAndBindAddedWorkspaceApps(final Context context,                                      
 412             final ArrayList<ItemInfo> workspaceApps) {                                                   
 413         final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                        
 414                                                                                                          
 415         if (workspaceApps == null) {                                                                     
 416             throw new RuntimeException("workspaceApps and allAppsApps must not be null");                
 417         }                                                                                                
 418         if (workspaceApps.isEmpty()) {                                                                   
 419             return;                                                                                      
 420         }                                                                                                
 421         // Process the newly added applications and add them to the database first                       
 422         Runnable r = new Runnable() {                                                                    
 423             public void run() {                                                                          
 424                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();               
 425                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                
 426                 final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                   
 427                                                                                                          
 428                 // Get the list of workspace screens.  We need to append to this list and                
 429                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been             
 430                 // called.                                                                               
 431                 ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                
 432                 TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                 
 433                 for (Integer i : orderedScreens.keySet()) {                                              
 434                     long screenId = orderedScreens.get(i);                                               
 435                     workspaceScreens.add(screenId);                                                      
 436                 }                                                                                        
 437                                                                                                          
 438                 synchronized(sBgLock) {                                                                  
 439                     Iterator<ItemInfo> iter = workspaceApps.iterator();                                  
 440                     while (iter.hasNext()) {                                                             
 441                         ItemInfo a = iter.next();                                                        
 442                         final String name = a.title.toString();                                          
 443                         final Intent launchIntent = a.getIntent();                                       
 444                                                                                                          
 445                         // Short-circuit this logic if the icon exists somewhere on the workspace        
 446                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {                 
 447                             // Only InstallShortcutReceiver sends us shortcutInfos, ignore them          
 448                             if (a instanceof AppInfo &&                                                  
 449                                     LauncherModel.appWasPromise(context, launchIntent, a.user)) {        
 450                                 restoredAppsFinal.add((AppInfo) a);                                      
 451                             }                                                                            
 452                             continue;                                                                    
 453                         }                                                                                
 454                                                                                                          
 455                         // Add this icon to the db, creating a new page if necessary.  If there          
 456                         // is only the empty page then we just add items to the first page.              
 457                         // Otherwise, we add them to the next pages.                                     
 458                         int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;                   
 459                         Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,     
 460                                 name, launchIntent, startSearchPageIndex, workspaceScreens);             
 461                         if (coords == null) {                                                            
 462                             LauncherProvider lp = LauncherAppState.getLauncherProvider();                
 463                                                                                                          
 464                             // If we can't find a valid position, then just add a new screen.            
 465                             // This takes time so we need to re-queue the add until the new              
 466                             // page is added.  Create as many screens as necessary to satisfy            
 467                             // the startSearchPageIndex.                                                 
 468                             int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -                   
 469                                     workspaceScreens.size());                                            
 470                             while (numPagesToAdd > 0) {                                                  
 471                                 long screenId = lp.generateNewScreenId();                                
 472                                 // Save the screen id for binding in the workspace                       
 473                                 workspaceScreens.add(screenId);                                          
 474                                 addedWorkspaceScreensFinal.add(screenId);                                
 475                                 numPagesToAdd--;                                                         
 476                             }                                                                            
 477                                                                                                          
 478                             // Find the coordinate again                                                 
 479                             coords = LauncherModel.findNextAvailableIconSpace(context,                   
 480                                     name, launchIntent, startSearchPageIndex, workspaceScreens);         
 481                         }                                                                                
 482                         if (coords == null) {                                                            
 483                             throw new RuntimeException("Coordinates should not be null");                
 484                         }                                                                                
 485                                                                                                          
 486                         ShortcutInfo shortcutInfo;                                                       
 487                         if (a instanceof ShortcutInfo) {                                                 
 488                             shortcutInfo = (ShortcutInfo) a;                                             
 489                         } else if (a instanceof AppInfo) {                                               
 490                             shortcutInfo = ((AppInfo) a).makeShortcut();                                 
 491                         } else {                                                                         
 492                             throw new RuntimeException("Unexpected info type");                          
 493                         }                                                                                
 494                                                                                                          
 495                         // Add the shortcut to the db                                                    
 496                         addItemToDatabase(context, shortcutInfo,                                         
 497                                 LauncherSettings.Favorites.CONTAINER_DESKTOP,                            
 498                                 coords.first, coords.second[0], coords.second[1], false);                
 499                         // Save the ShortcutInfo for binding in the workspace                            
 500                         addedShortcutsFinal.add(shortcutInfo);                                           
 501                     }                                                                                    
 502                 }                                                                                        
 503                                                                                                          
 504                 // Update the workspace screens                                                          
 505                 updateWorkspaceScreenOrder(context, workspaceScreens);                                   
 506                                                                                                          
 507                 if (!addedShortcutsFinal.isEmpty()) {                                                    
 508                     runOnMainThread(new Runnable() {                                                     
 509                         public void run() {                                                              
 510                             Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                 
 511                             if (callbacks == cb && cb != null) {                                         
 512                                 final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();       
 513                                 final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();    
 514                                 if (!addedShortcutsFinal.isEmpty()) {                                    
 515                                     ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 🔵
 516                                     long lastScreenId = info.screenId;                                   
 517                                     for (ItemInfo i : addedShortcutsFinal) {                             
 518                                         if (i.screenId == lastScreenId) {                                
 519                                             addAnimated.add(i);                                          
 520                                         } else {                                                         
 521                                             addNotAnimated.add(i);                                       
 522                                         }                                                                
 523                                     }                                                                    
 524                                 }                                                                        
 525                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal,                      
 526                                         addNotAnimated, addAnimated, null);                              
 527                                 if (!restoredAppsFinal.isEmpty()) {                                      
 528                                     callbacks.bindAppsUpdated(restoredAppsFinal);                        
 529                                 }                                                                        
 530                             }                                                                            
 531                         }                                                                                
 532                     });                                                                                  
 533                 }                                                                                        
 534             }                                                                                            
 535         };                                                                                               
 536         runOnWorkerThread(r);                                                                            
 537     }                                                                                                    
 538                                                                                                          
 539     public void unbindItemInfosAndClearQueuedBindRunnables() {                                           
 540         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 541             throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +     
 542                     "main thread");                                                                      
 543         }                                                                                                
 544                                                                                                          
 545         // Clear any deferred bind runnables                                                             
 546         synchronized (mDeferredBindRunnables) {                                                          
 547             mDeferredBindRunnables.clear();                                                              
 548         }                                                                                                
 549         // Remove any queued bind runnables                                                              
 550         mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);                                 
 551         // Unbind all the workspace items                                                                
 552         unbindWorkspaceItemsOnMainThread();                                                              
 553     }                                                                                                    
 554                                                                                                          
 555     /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */                        
 556     void unbindWorkspaceItemsOnMainThread() {                                                            
 557         // Ensure that we don't use the same workspace items data structure on the main thread           
 558         // by making a copy of workspace items first.                                                    
 559         final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();                         
 560         final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();                             
 561         synchronized (sBgLock) {                                                                         
 562             tmpWorkspaceItems.addAll(sBgWorkspaceItems);                                                 
 563             tmpAppWidgets.addAll(sBgAppWidgets);                                                         
 564         }                                                                                                
 565         Runnable r = new Runnable() {                                                                    
 566                 @Override                                                                                
 567                 public void run() {                                                                      
 568                    for (ItemInfo item : tmpWorkspaceItems) {                                             
 569                        item.unbind();                                                                    
 570                    }                                                                                     
 571                    for (ItemInfo item : tmpAppWidgets) {                                                 
 572                        item.unbind();                                                                    
 573                    }                                                                                     
 574                 }                                                                                        
 575             };                                                                                           
 576         runOnMainThread(r);                                                                              
 577     }                                                                                                    
 578                                                                                                          
 579     /**                                                                                                  
 580      * Adds an item to the DB if it was not created previously, or move it to a new                      
 581      * <container, screen, cellX, cellY>                                                                 
 582      */                                                                                                  
 583     static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,                  
 584             long screenId, int cellX, int cellY) {                                                       
 585         if (item.container == ItemInfo.NO_ID) {                                                          
 586             // From all apps                                                                             
 587             addItemToDatabase(context, item, container, screenId, cellX, cellY, false);                  
 588         } else {                                                                                         
 589             // From somewhere else                                                                       
 590             moveItemInDatabase(context, item, container, screenId, cellX, cellY);                        
 591         }                                                                                                
 592     }                                                                                                    
 593                                                                                                          
 594     static void checkItemInfoLocked(                                                                     
 595             final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {                    
 596         ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                                  
 597         if (modelItem != null && item != modelItem) {                                                    
 598             // check all the data is consistent                                                          
 599             if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {                     
 600                 ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;                                   
 601                 ShortcutInfo shortcut = (ShortcutInfo) item;                                             
 602                 if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&                  
 603                         modelShortcut.intent.filterEquals(shortcut.intent) &&                            
 604                         modelShortcut.id == shortcut.id &&                                               
 605                         modelShortcut.itemType == shortcut.itemType &&                                   
 606                         modelShortcut.container == shortcut.container &&                                 
 607                         modelShortcut.screenId == shortcut.screenId &&                                   
 608                         modelShortcut.cellX == shortcut.cellX &&                                         
 609                         modelShortcut.cellY == shortcut.cellY &&                                         
 610                         modelShortcut.spanX == shortcut.spanX &&                                         
 611                         modelShortcut.spanY == shortcut.spanY &&                                         
 612                         ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||                  
 613                         (modelShortcut.dropPos != null &&                                                
 614                                 shortcut.dropPos != null &&                                              
 615                                 modelShortcut.dropPos[0] == shortcut.dropPos[0] &&                       
 616                         modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {                             
 617                     // For all intents and purposes, this is the same object                             
 618                     return;                                                                              
 619                 }                                                                                        
 620             }                                                                                            
 621                                                                                                          
 622             // the modelItem needs to match up perfectly with item if our model is                       
 623             // to be consistent with the database-- for now, just require                                
 624             // modelItem == item or the equality check above                                             
 625             String msg = "item: " + ((item != null) ? item.toString() : "null") +                        
 626                     "modelItem: " +                                                                      
 627                     ((modelItem != null) ? modelItem.toString() : "null") +                              
 628                     "Error: ItemInfo passed to checkItemInfo doesn't match original";                    
 629             RuntimeException e = new RuntimeException(msg);                                              
 630             if (stackTrace != null) {                                                                    
 631                 e.setStackTrace(stackTrace);                                                             
 632             }                                                                                            
 633             throw e;                                                                                     
 634         }                                                                                                
 635     }                                                                                                    
 636                                                                                                          
 637     static void checkItemInfo(final ItemInfo item) {                                                     
 638         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 639         final long itemId = item.id;                                                                     
 640         Runnable r = new Runnable() {                                                                    
 641             public void run() {                                                                          
 642                 synchronized (sBgLock) {                                                                 
 643                     checkItemInfoLocked(itemId, item, stackTrace);                                       
 644                 }                                                                                        
 645             }                                                                                            
 646         };                                                                                               
 647         runOnWorkerThread(r);                                                                            
 648     }                                                                                                    
 649                                                                                                          
 650     static void updateItemInDatabaseHelper(Context context, final ContentValues values,                  
 651             final ItemInfo item, final String callingFunction) {                                         
 652         final long itemId = item.id;                                                                     
 653         final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);                         
 654         final ContentResolver cr = context.getContentResolver();                                         
 655                                                                                                          
 656         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 657         Runnable r = new Runnable() {                                                                    
 658             public void run() {                                                                          
 659                 cr.update(uri, values, null, null);                                                      
 660                 updateItemArrays(item, itemId, stackTrace);                                              
 661             }                                                                                            
 662         };                                                                                               
 663         runOnWorkerThread(r);                                                                            
 664     }                                                                                                    
 665                                                                                                          
 666     static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,  
 667             final ArrayList<ItemInfo> items, final String callingFunction) {                             
 668         final ContentResolver cr = context.getContentResolver();                                         
 669                                                                                                          
 670         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 671         Runnable r = new Runnable() {                                                                    
 672             public void run() {                                                                          
 673                 ArrayList<ContentProviderOperation> ops =                                                
 674                         new ArrayList<ContentProviderOperation>();                                       
 675                 int count = items.size();                                                                
 676                 for (int i = 0; i < count; i++) {                                                        
 677                     ItemInfo item = items.get(i);                                                        
 678                     final long itemId = item.id;                                                         
 679                     final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);             
 680                     ContentValues values = valuesList.get(i);                                            
 681                                                                                                          
 682                     ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());         
 683                     updateItemArrays(item, itemId, stackTrace);                                          
 684                                                                                                          
 685                 }                                                                                        
 686                 try {                                                                                    
 687                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
 688                 } catch (Exception e) {                                                                  
 689                     e.printStackTrace();                                                                 
 690                 }                                                                                        
 691             }                                                                                            
 692         };                                                                                               
 693         runOnWorkerThread(r);                                                                            
 694     }                                                                                                    
 695                                                                                                          
 696     static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {           
 697         // Lock on mBgLock *after* the db operation                                                      
 698         synchronized (sBgLock) {                                                                         
 699             checkItemInfoLocked(itemId, item, stackTrace);                                               
 700                                                                                                          
 701             if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&                        
 702                     item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                    
 703                 // Item is in a folder, make sure this folder exists                                     
 704                 if (!sBgFolders.containsKey(item.container)) {                                           
 705                     // An items container is being set to a that of an item which is not in              
 706                     // the list of Folders.                                                              
 707                     String msg = "item: " + item + " container being set to: " +                         
 708                             item.container + ", not in the list of folders";                             
 709                     Log.e(TAG, msg);                                                                     
 710                 }                                                                                        
 711             }                                                                                            
 712                                                                                                          
 713             // Items are added/removed from the corresponding FolderInfo elsewhere, such                 
 714             // as in Workspace.onDrop. Here, we just add/remove them from the list of items              
 715             // that are on the desktop, as appropriate                                                   
 716             ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                              
 717             if (modelItem != null &&                                                                     
 718                     (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||              
 719                      modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {             
 720                 switch (modelItem.itemType) {                                                            
 721                     case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                               
 722                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                  
 723                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                    
 724                         if (!sBgWorkspaceItems.contains(modelItem)) {                                    
 725                             sBgWorkspaceItems.add(modelItem);                                            
 726                         }                                                                                
 727                         break;                                                                           
 728                     default:                                                                             
 729                         break;                                                                           
 730                 }                                                                                        
 731             } else {                                                                                     
 732                 sBgWorkspaceItems.remove(modelItem);                                                     
 733             }                                                                                            
 734         }                                                                                                
 735     }                                                                                                    
 736                                                                                                          
 737     public void flushWorkerThread() {                                                                    
 738         mFlushingWorkerThread = true;                                                                    
 739         Runnable waiter = new Runnable() {                                                               
 740                 public void run() {                                                                      
 741                     synchronized (this) {                                                                
 742                         notifyAll();                                                                     
 743                         mFlushingWorkerThread = false;                                                   
 744                     }                                                                                    
 745                 }                                                                                        
 746             };                                                                                           
 747                                                                                                          
 748         synchronized(waiter) {                                                                           
 749             runOnWorkerThread(waiter);                                                                   
 750             if (mLoaderTask != null) {                                                                   
 751                 synchronized(mLoaderTask) {                                                              
 752                     mLoaderTask.notify();                                                                
 753                 }                                                                                        
 754             }                                                                                            
 755             boolean success = false;                                                                     
 756             while (!success) {                                                                           
 757                 try {                                                                                    
 758                     waiter.wait();                                                                       
 759                     success = true;                                                                      
 760                 } catch (InterruptedException e) {                                                       
 761                 }                                                                                        
 762             }                                                                                            
 763         }                                                                                                
 764     }                                                                                                    
 765                                                                                                          
 766     /**                                                                                                  
 767      * Move an item in the DB to a new <container, screen, cellX, cellY>                                 
 768      */                                                                                                  
 769     static void moveItemInDatabase(Context context, final ItemInfo item, final long container,           
 770             final long screenId, final int cellX, final int cellY) {                                     
 771         item.container = container;                                                                      
 772         item.cellX = cellX;                                                                              
 773         item.cellY = cellY;                                                                              
 774                                                                                                          
 775         // We store hotseat items in canonical form which is this orientation invariant position         
 776         // in the hotseat                                                                                
 777         if (context instanceof Launcher && screenId < 0 &&                                               
 778                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
 779             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
 780         } else {                                                                                         
 781             item.screenId = screenId;                                                                    
 782         }                                                                                                
 783                                                                                                          
 784         final ContentValues values = new ContentValues();                                                
 785         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
 786         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
 787         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
 788         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
 789                                                                                                          
 790         updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");                         
 791     }                                                                                                    
 792                                                                                                          
 793     /**                                                                                                  
 794      * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the               
 795      * cellX, cellY have already been updated on the ItemInfos.                                          
 796      */                                                                                                  
 797     static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,                    
 798             final long container, final int screen) {                                                    
 799                                                                                                          
 800         ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();                         
 801         int count = items.size();                                                                        
 802                                                                                                          
 803         for (int i = 0; i < count; i++) {                                                                
 804             ItemInfo item = items.get(i);                                                                
 805             item.container = container;                                                                  
 806                                                                                                          
 807             // We store hotseat items in canonical form which is this orientation invariant position     
 808             // in the hotseat                                                                            
 809             if (context instanceof Launcher && screen < 0 &&                                             
 810                     container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                         
 811                 item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,          
 812                         item.cellY);                                                                     
 813             } else {                                                                                     
 814                 item.screenId = screen;                                                                  
 815             }                                                                                            
 816                                                                                                          
 817             final ContentValues values = new ContentValues();                                            
 818             values.put(LauncherSettings.Favorites.CONTAINER, item.container);                            
 819             values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                    
 820             values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                    
 821             values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                
 822                                                                                                          
 823             contentValues.add(values);                                                                   
 824         }                                                                                                
 825         updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");                
 826     }                                                                                                    
 827                                                                                                          
 828     /**                                                                                                  
 829      * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>        
 830      */                                                                                                  
 831     static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,         
 832             final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {   
 833         item.container = container;                                                                      
 834         item.cellX = cellX;                                                                              
 835         item.cellY = cellY;                                                                              
 836         item.spanX = spanX;                                                                              
 837         item.spanY = spanY;                                                                              
 838                                                                                                          
 839         // We store hotseat items in canonical form which is this orientation invariant position         
 840         // in the hotseat                                                                                
 841         if (context instanceof Launcher && screenId < 0 &&                                               
 842                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
 843             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
 844         } else {                                                                                         
 845             item.screenId = screenId;                                                                    
 846         }                                                                                                
 847                                                                                                          
 848         final ContentValues values = new ContentValues();                                                
 849         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
 850         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
 851         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
 852         values.put(LauncherSettings.Favorites.SPANX, item.spanX);                                        
 853         values.put(LauncherSettings.Favorites.SPANY, item.spanY);                                        
 854         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
 855                                                                                                          
 856         updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");                       
 857     }                                                                                                    
 858                                                                                                          
 859     /**                                                                                                  
 860      * Update an item to the database in a specified container.                                          
 861      */                                                                                                  
 862     static void updateItemInDatabase(Context context, final ItemInfo item) {                             
 863         final ContentValues values = new ContentValues();                                                
 864         item.onAddToDatabase(context, values);                                                           
 865         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
 866         updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");                       
 867     }                                                                                                    
 868                                                                                                          
 869     /**                                                                                                  
 870      * Returns true if the shortcuts already exists in the database.                                     
 871      * we identify a shortcut by its title and intent.                                                   
 872      */                                                                                                  
 873     static boolean shortcutExists(Context context, String title, Intent intent) {                        
 874         final ContentResolver cr = context.getContentResolver();                                         
 875         final Intent intentWithPkg, intentWithoutPkg;                                                    
 876                                                                                                          
 877         if (intent.getComponent() != null) {                                                             
 878             // If component is not null, an intent with null package will produce                        
 879             // the same result and should also be a match.                                               
 880             if (intent.getPackage() != null) {                                                           
 881                 intentWithPkg = intent;                                                                  
 882                 intentWithoutPkg = new Intent(intent).setPackage(null);                                  
 883             } else {                                                                                     
 884                 intentWithPkg = new Intent(intent).setPackage(                                           
 885                         intent.getComponent().getPackageName());                                         
 886                 intentWithoutPkg = intent;                                                               
 887             }                                                                                            
 888         } else {                                                                                         
 889             intentWithPkg = intent;                                                                      
 890             intentWithoutPkg = intent;                                                                   
 891         }                                                                                                
 892         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,                                      
 893             new String[] { "title", "intent" }, "title=? and (intent=? or intent=?)",                    
 894             new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0) }, null);            
 895         boolean result = false;                                                                          
 896         try {                                                                                            
 897             result = c.moveToFirst();                                                                    
 898         } finally {                                                                                      
 899             c.close();                                                                                   
 900         }                                                                                                
 901         return result;                                                                                   
 902     }                                                                                                    
 903                                                                                                          
 904     /**                                                                                                  
 905      * Returns true if the promise shortcuts with the same package name exists on the workspace.         
 906      */                                                                                                  
 907     static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {                
 908         final ComponentName component = intent.getComponent();                                           
 909         if (component == null) {                                                                         
 910             return false;                                                                                
 911         }                                                                                                
 912         return !getItemsByPackageName(component.getPackageName(), user).isEmpty();                       
 913     }                                                                                                    
 914                                                                                                          
 915     /**                                                                                                  
 916      * Returns an ItemInfo array containing all the items in the LauncherModel.                          
 917      * The ItemInfo.id is not set through this function.                                                 
 918      */                                                                                                  
 919     static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {                             
 920         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
 921         final ContentResolver cr = context.getContentResolver();                                         
 922         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {                       
 923                 LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,              
 924                 LauncherSettings.Favorites.SCREEN,                                                       
 925                 LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,                      
 926                 LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY,                      
 927                 LauncherSettings.Favorites.PROFILE_ID }, null, null, null);                              
 928                                                                                                          
 929         final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);         
 930         final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);        
 931         final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);              
 932         final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                
 933         final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                
 934         final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);                
 935         final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);                
 936         final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);       
 937         UserManagerCompat userManager = UserManagerCompat.getInstance(context);                          
 938         try {                                                                                            
 939             while (c.moveToNext()) {                                                                     
 940                 ItemInfo item = new ItemInfo();                                                          
 941                 item.cellX = c.getInt(cellXIndex);                                                       
 942                 item.cellY = c.getInt(cellYIndex);                                                       
 943                 item.spanX = Math.max(1, c.getInt(spanXIndex));                                          
 944                 item.spanY = Math.max(1, c.getInt(spanYIndex));                                          
 945                 item.container = c.getInt(containerIndex);                                               
 946                 item.itemType = c.getInt(itemTypeIndex);                                                 
 947                 item.screenId = c.getInt(screenIndex);                                                   
 948                 long serialNumber = c.getInt(profileIdIndex);                                            
 949                 item.user = userManager.getUserForSerialNumber(serialNumber);                            
 950                 // Skip if user has been deleted.                                                        
 951                 if (item.user != null) {                                                                 
 952                     items.add(item);                                                                     
 953                 }                                                                                        
 954             }                                                                                            
 955         } catch (Exception e) {                                                                          
 956             items.clear();                                                                               
 957         } finally {                                                                                      
 958             c.close();                                                                                   
 959         }                                                                                                
 960                                                                                                          
 961         return items;                                                                                    
 962     }                                                                                                    
 963                                                                                                          
 964     /**                                                                                                  
 965      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.       
 966      */                                                                                                  
 967     FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {            
 968         final ContentResolver cr = context.getContentResolver();                                         
 969         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,                                
 970                 "_id=? and (itemType=? or itemType=?)",                                                  
 971                 new String[] { String.valueOf(id),                                                       
 972                         String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);             
 973                                                                                                          
 974         try {                                                                                            
 975             if (c.moveToFirst()) {                                                                       
 976                 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); 
 977                 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);        
 978                 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
 979                 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);      
 980                 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);        
 981                 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);        
 982                                                                                                          
 983                 FolderInfo folderInfo = null;                                                            
 984                 switch (c.getInt(itemTypeIndex)) {                                                       
 985                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                    
 986                         folderInfo = findOrMakeFolder(folderList, id);                                   
 987                         break;                                                                           
 988                 }                                                                                        
 989                                                                                                          
 990                 folderInfo.title = c.getString(titleIndex);                                              
 991                 folderInfo.id = id;                                                                      
 992                 folderInfo.container = c.getInt(containerIndex);                                         
 993                 folderInfo.screenId = c.getInt(screenIndex);                                             
 994                 folderInfo.cellX = c.getInt(cellXIndex);                                                 
 995                 folderInfo.cellY = c.getInt(cellYIndex);                                                 
 996                                                                                                          
 997                 return folderInfo;                                                                       
 998             }                                                                                            
 999         } finally {                                                                                      
1000             c.close();                                                                                   
1001         }                                                                                                
1002                                                                                                          
1003         return null;                                                                                     
1004     }                                                                                                    
1005                                                                                                          
1006     /**                                                                                                  
1007      * Add an item to the database in a specified container. Sets the container, screen, cellX and       
1008      * cellY fields of the item. Also assigns an ID to the item.                                         
1009      */                                                                                                  
1010     static void addItemToDatabase(Context context, final ItemInfo item, final long container,            
1011             final long screenId, final int cellX, final int cellY, final boolean notify) {               
1012         item.container = container;                                                                      
1013         item.cellX = cellX;                                                                              
1014         item.cellY = cellY;                                                                              
1015         // We store hotseat items in canonical form which is this orientation invariant position         
1016         // in the hotseat                                                                                
1017         if (context instanceof Launcher && screenId < 0 &&                                               
1018                 container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
1019             item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);           
1020         } else {                                                                                         
1021             item.screenId = screenId;                                                                    
1022         }                                                                                                
1023                                                                                                          
1024         final ContentValues values = new ContentValues();                                                
1025         final ContentResolver cr = context.getContentResolver();                                         
1026         item.onAddToDatabase(context, values);                                                           
1027                                                                                                          
1028         item.id = LauncherAppState.getLauncherProvider().generateNewItemId();                            
1029         values.put(LauncherSettings.Favorites._ID, item.id);                                             
1030         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
1031                                                                                                          
1032         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
1033         Runnable r = new Runnable() {                                                                    
1034             public void run() {                                                                          
1035                 cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :                              
1036                         LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);                 
1037                                                                                                          
1038                 // Lock on mBgLock *after* the db operation                                              
1039                 synchronized (sBgLock) {                                                                 
1040                     checkItemInfoLocked(item.id, item, stackTrace);                                      
1041                     sBgItemsIdMap.put(item.id, item);                                                    
1042                     switch (item.itemType) {                                                             
1043                         case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                
1044                             sBgFolders.put(item.id, (FolderInfo) item);                                  
1045                             // Fall through                                                              
1046                         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                           
1047                         case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                              
1048                             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||        
1049                                     item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {    
1050                                 sBgWorkspaceItems.add(item);                                             
1051                             } else {                                                                     
1052                                 if (!sBgFolders.containsKey(item.container)) {                           
1053                                     // Adding an item to a folder that doesn't exist.                    
1054                                     String msg = "adding item: " + item + " to a folder that " +         
1055                                             " doesn't exist";                                            
1056                                     Log.e(TAG, msg);                                                     
1057                                 }                                                                        
1058                             }                                                                            
1059                             break;                                                                       
1060                         case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                             
1061                             sBgAppWidgets.add((LauncherAppWidgetInfo) item);                             
1062                             break;                                                                       
1063                     }                                                                                    
1064                 }                                                                                        
1065             }                                                                                            
1066         };                                                                                               
1067         runOnWorkerThread(r);                                                                            
1068     }                                                                                                    
1069                                                                                                          
1070     /**                                                                                                  
1071      * Creates a new unique child id, for a given cell span across all layouts.                          
1072      */                                                                                                  
1073     static int getCellLayoutChildId(                                                                     
1074             long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {         
1075         return (((int) container & 0xFF) << 24)                                                          
1076                 | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);          
1077     }                                                                                                    
1078                                                                                                          
1079     private static ArrayList<ItemInfo> getItemsByPackageName(                                            
1080             final String pn, final UserHandleCompat user) {                                              
1081         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
1082             @Override                                                                                    
1083             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
1084                 return cn.getPackageName().equals(pn) && info.user.equals(user);                         
1085             }                                                                                            
1086         };                                                                                               
1087         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
1088     }                                                                                                    
1089                                                                                                          
1090     /**                                                                                                  
1091      * Removes all the items from the database corresponding to the specified package.                   
1092      */                                                                                                  
1093     static void deletePackageFromDatabase(Context context, final String pn,                              
1094             final UserHandleCompat user) {                                                               
1095         deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));                               
1096     }                                                                                                    
1097                                                                                                          
1098     /**                                                                                                  
1099      * Removes the specified item from the database                                                      
1100      * @param context                                                                                    
1101      * @param item                                                                                       
1102      */                                                                                                  
1103     static void deleteItemFromDatabase(Context context, final ItemInfo item) {                           
1104         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
1105         items.add(item);                                                                                 
1106         deleteItemsFromDatabase(context, items);                                                         
1107     }                                                                                                    
1108                                                                                                          
1109     /**                                                                                                  
1110      * Removes the specified items from the database                                                     
1111      * @param context                                                                                    
1112      * @param item                                                                                       
1113      */                                                                                                  
1114     static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {              
1115         final ContentResolver cr = context.getContentResolver();                                         
1116                                                                                                          
1117         Runnable r = new Runnable() {                                                                    
1118             public void run() {                                                                          
1119                 for (ItemInfo item : items) {                                                            
1120                     final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);            
1121                     cr.delete(uri, null, null);                                                          
1122                                                                                                          
1123                     // Lock on mBgLock *after* the db operation                                          
1124                     synchronized (sBgLock) {                                                             
1125                         switch (item.itemType) {                                                         
1126                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                            
1127                                 sBgFolders.remove(item.id);                                              
1128                                 for (ItemInfo info: sBgItemsIdMap.values()) {                            
1129                                     if (info.container == item.id) {                                     
1130                                         // We are deleting a folder which still contains items that      
1131                                         // think they are contained by that folder.                      
1132                                         String msg = "deleting a folder (" + item + ") which still " +   
1133                                                 "contains items (" + info + ")";                         
1134                                         Log.e(TAG, msg);                                                 
1135                                     }                                                                    
1136                                 }                                                                        
1137                                 sBgWorkspaceItems.remove(item);                                          
1138                                 break;                                                                   
1139                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                       
1140                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                          
1141                                 sBgWorkspaceItems.remove(item);                                          
1142                                 break;                                                                   
1143                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                         
1144                                 sBgAppWidgets.remove((LauncherAppWidgetInfo) item);                      
1145                                 break;                                                                   
1146                         }                                                                                
1147                         sBgItemsIdMap.remove(item.id);                                                   
1148                         sBgDbIconCache.remove(item);                                                     
1149                     }                                                                                    
1150                 }                                                                                        
1151             }                                                                                            
1152         };                                                                                               
1153         runOnWorkerThread(r);                                                                            
1154     }                                                                                                    
1155                                                                                                          
1156     /**                                                                                                  
1157      * Update the order of the workspace screens in the database. The array list contains                
1158      * a list of screen ids in the order that they should appear.                                        
1159      */                                                                                                  
1160     void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {                    
1161         // Log to disk                                                                                   
1162         Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);                       
1163         Launcher.addDumpLog(TAG, "11683562 -   screens: " + TextUtils.join(", ", screens), true);        
1164                                                                                                          
1165         final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);                                
1166         final ContentResolver cr = context.getContentResolver();                                         
1167         final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                                   
1168                                                                                                          
1169         // Remove any negative screen ids -- these aren't persisted                                      
1170         Iterator<Long> iter = screensCopy.iterator();                                                    
1171         while (iter.hasNext()) {                                                                         
1172             long id = iter.next();                                                                       
1173             if (id < 0) {                                                                                
1174                 iter.remove();                                                                           
1175             }                                                                                            
1176         }                                                                                                
1177                                                                                                          
1178         Runnable r = new Runnable() {                                                                    
1179             @Override                                                                                    
1180             public void run() {                                                                          
1181                 ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();     
1182                 // Clear the table                                                                       
1183                 ops.add(ContentProviderOperation.newDelete(uri).build());                                
1184                 int count = screensCopy.size();                                                          
1185                 for (int i = 0; i < count; i++) {                                                        
1186                     ContentValues v = new ContentValues();                                               
1187                     long screenId = screensCopy.get(i);                                                  
1188                     v.put(LauncherSettings.WorkspaceScreens._ID, screenId);                              
1189                     v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);                             
1190                     ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());              
1191                 }                                                                                        
1192                                                                                                          
1193                 try {                                                                                    
1194                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
1195                 } catch (Exception ex) {                                                                 
1196                     throw new RuntimeException(ex);                                                      
1197                 }                                                                                        
1198                                                                                                          
1199                 synchronized (sBgLock) {                                                                 
1200                     sBgWorkspaceScreens.clear();                                                         
1201                     sBgWorkspaceScreens.addAll(screensCopy);                                             
1202                 }                                                                                        
1203             }                                                                                            
1204         };                                                                                               
1205         runOnWorkerThread(r);                                                                            
1206     }                                                                                                    
1207                                                                                                          
1208     /**                                                                                                  
1209      * Remove the contents of the specified folder from the database                                     
1210      */                                                                                                  
1211     static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {               
1212         final ContentResolver cr = context.getContentResolver();                                         
1213                                                                                                          
1214         Runnable r = new Runnable() {                                                                    
1215             public void run() {                                                                          
1216                 cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);         
1217                 // Lock on mBgLock *after* the db operation                                              
1218                 synchronized (sBgLock) {                                                                 
1219                     sBgItemsIdMap.remove(info.id);                                                       
1220                     sBgFolders.remove(info.id);                                                          
1221                     sBgDbIconCache.remove(info);                                                         
1222                     sBgWorkspaceItems.remove(info);                                                      
1223                 }                                                                                        
1224                                                                                                          
1225                 cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,                        
1226                         LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);                     
1227                 // Lock on mBgLock *after* the db operation                                              
1228                 synchronized (sBgLock) {                                                                 
1229                     for (ItemInfo childInfo : info.contents) {                                           
1230                         sBgItemsIdMap.remove(childInfo.id);                                              
1231                         sBgDbIconCache.remove(childInfo);                                                
1232                     }                                                                                    
1233                 }                                                                                        
1234             }                                                                                            
1235         };                                                                                               
1236         runOnWorkerThread(r);                                                                            
1237     }                                                                                                    
1238                                                                                                          
1239     /**                                                                                                  
1240      * Set this as the current Launcher activity object for the loader.                                  
1241      */                                                                                                  
1242     public void initialize(Callbacks callbacks) {                                                        
1243         synchronized (mLock) {                                                                           
1244             mCallbacks = new WeakReference<Callbacks>(callbacks);                                        
1245         }                                                                                                
1246     }                                                                                                    
1247                                                                                                          
1248     @Override                                                                                            
1249     public void onPackageChanged(String packageName, UserHandleCompat user) {                            
1250         int op = PackageUpdatedTask.OP_UPDATE;                                                           
1251         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1252                 user));                                                                                  
1253     }                                                                                                    
1254                                                                                                          
1255     @Override                                                                                            
1256     public void onPackageRemoved(String packageName, UserHandleCompat user) {                            
1257         int op = PackageUpdatedTask.OP_REMOVE;                                                           
1258         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1259                 user));                                                                                  
1260     }                                                                                                    
1261                                                                                                          
1262     @Override                                                                                            
1263     public void onPackageAdded(String packageName, UserHandleCompat user) {                              
1264         int op = PackageUpdatedTask.OP_ADD;                                                              
1265         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                   
1266                 user));                                                                                  
1267     }                                                                                                    
1268                                                                                                          
1269     @Override                                                                                            
1270     public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,                        
1271             boolean replacing) {                                                                         
1272         if (!replacing) {                                                                                
1273             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames,        
1274                     user));                                                                              
1275             if (mAppsCanBeOnRemoveableStorage) {                                                         
1276                 // Only rebind if we support removable storage. It catches the                           
1277                 // case where                                                                            
1278                 // apps on the external sd card need to be reloaded                                      
1279                 startLoaderFromBackground();                                                             
1280             }                                                                                            
1281         } else {                                                                                         
1282             // If we are replacing then just update the packages in the list                             
1283             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,                   
1284                     packageNames, user));                                                                
1285         }                                                                                                
1286     }                                                                                                    
1287                                                                                                          
1288     @Override                                                                                            
1289     public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,                      
1290             boolean replacing) {                                                                         
1291         if (!replacing) {                                                                                
1292             enqueuePackageUpdated(new PackageUpdatedTask(                                                
1293                     PackageUpdatedTask.OP_UNAVAILABLE, packageNames,                                     
1294                     user));                                                                              
1295         }                                                                                                
1296                                                                                                          
1297     }                                                                                                    
1298                                                                                                          
1299     /**                                                                                                  
1300      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and                        
1301      * ACTION_PACKAGE_CHANGED.                                                                           
1302      */                                                                                                  
1303     @Override                                                                                            
1304     public void onReceive(Context context, Intent intent) {                                              
1305         if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);                                    
1306                                                                                                          
1307         final String action = intent.getAction();                                                        
1308         if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {                                               
1309             // If we have changed locale we need to clear out the labels in all apps/workspace.          
1310             forceReload();                                                                               
1311         } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {                                 
1312              // Check if configuration change was an mcc/mnc change which would affect app resources     
1313              // and we would need to clear out the labels in all apps/workspace. Same handling as        
1314              // above for ACTION_LOCALE_CHANGED                                                          
1315              Configuration currentConfig = context.getResources().getConfiguration();                    
1316              if (mPreviousConfigMcc != currentConfig.mcc) {                                              
1317                    Log.d(TAG, "Reload apps on config change. curr_mcc:"                                  
1318                        + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);                          
1319                    forceReload();                                                                        
1320              }                                                                                           
1321              // Update previousConfig                                                                    
1322              mPreviousConfigMcc = currentConfig.mcc;                                                     
1323         } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) ||                 
1324                    SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)) {                     
1325             if (mCallbacks != null) {                                                                    
1326                 Callbacks callbacks = mCallbacks.get();                                                  
1327                 if (callbacks != null) {                                                                 
1328                     callbacks.bindSearchablesChanged();                                                  
1329                 }                                                                                        
1330             }                                                                                            
1331         }                                                                                                
1332     }                                                                                                    
1333                                                                                                          
1334     void forceReload() {                                                                                 
1335         resetLoadedState(true, true);                                                                    
1336                                                                                                          
1337         // Do this here because if the launcher activity is running it will be restarted.                
1338         // If it's not running startLoaderFromBackground will merely tell it that it needs               
1339         // to reload.                                                                                    
1340         startLoaderFromBackground();                                                                     
1341     }                                                                                                    
1342                                                                                                          
1343     public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {             
1344         synchronized (mLock) {                                                                           
1345             // Stop any existing loaders first, so they don't set mAllAppsLoaded or                      
1346             // mWorkspaceLoaded to true later                                                            
1347             stopLoaderLocked();                                                                          
1348             if (resetAllAppsLoaded) mAllAppsLoaded = false;                                              
1349             if (resetWorkspaceLoaded) mWorkspaceLoaded = false;                                          
1350         }                                                                                                
1351     }                                                                                                    
1352                                                                                                          
1353     /**                                                                                                  
1354      * When the launcher is in the background, it's possible for it to miss paired                       
1355      * configuration changes.  So whenever we trigger the loader from the background                     
1356      * tell the launcher that it needs to re-run the loader when it comes back instead                   
1357      * of doing it now.                                                                                  
1358      */                                                                                                  
1359     public void startLoaderFromBackground() {                                                            
1360         boolean runLoader = false;                                                                       
1361         if (mCallbacks != null) {                                                                        
1362             Callbacks callbacks = mCallbacks.get();                                                      
1363             if (callbacks != null) {                                                                     
1364                 // Only actually run the loader if they're not paused.                                   
1365                 if (!callbacks.setLoadOnResume()) {                                                      
1366                     runLoader = true;                                                                    
1367                 }                                                                                        
1368             }                                                                                            
1369         }                                                                                                
1370         if (runLoader) {                                                                                 
1371             startLoader(false, PagedView.INVALID_RESTORE_PAGE);                                          
1372         }                                                                                                
1373     }                                                                                                    
1374                                                                                                          
1375     // If there is already a loader task running, tell it to stop.                                       
1376     // returns true if isLaunching() was true on the old task                                            
1377     private boolean stopLoaderLocked() {                                                                 
1378         boolean isLaunching = false;                                                                     
1379         LoaderTask oldTask = mLoaderTask;                                                                
1380         if (oldTask != null) {                                                                           
1381             if (oldTask.isLaunching()) {                                                                 
1382                 isLaunching = true;                                                                      
1383             }                                                                                            
1384             oldTask.stopLocked();                                                                        
1385         }                                                                                                
1386         return isLaunching;                                                                              
1387     }                                                                                                    
1388                                                                                                          
1389     public boolean isCurrentCallbacks(Callbacks callbacks) {                                             
1390         return (mCallbacks != null && mCallbacks.get() == callbacks);                                    
1391     }                                                                                                    
1392                                                                                                          
1393     public void startLoader(boolean isLaunching, int synchronousBindPage) {                              
1394         startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);                                 
1395     }                                                                                                    
1396                                                                                                          
1397     public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {               
1398         synchronized (mLock) {                                                                           
1399             if (DEBUG_LOADERS) {                                                                         
1400                 Log.d(TAG, "startLoader isLaunching=" + isLaunching);                                    
1401             }                                                                                            
1402                                                                                                          
1403             // Clear any deferred bind-runnables from the synchronized load process                      
1404             // We must do this before any loading/binding is scheduled below.                            
1405             synchronized (mDeferredBindRunnables) {                                                      
1406                 mDeferredBindRunnables.clear();                                                          
1407             }                                                                                            
1408                                                                                                          
1409             // Don't bother to start the thread if we know it's not going to do anything                 
1410             if (mCallbacks != null && mCallbacks.get() != null) {                                        
1411                 // If there is already one running, tell it to stop.                                     
1412                 // also, don't downgrade isLaunching if we're already running                            
1413                 isLaunching = isLaunching || stopLoaderLocked();                                         
1414                 mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);                 
1415                 if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE                                
1416                         && mAllAppsLoaded && mWorkspaceLoaded) {                                         
1417                     mLoaderTask.runBindSynchronousPage(synchronousBindPage);                             
1418                 } else {                                                                                 
1419                     sWorkerThread.setPriority(Thread.NORM_PRIORITY);                                     
1420                     sWorker.post(mLoaderTask);                                                           
1421                 }                                                                                        
1422             }                                                                                            
1423         }                                                                                                
1424     }                                                                                                    
1425                                                                                                          
1426     void bindRemainingSynchronousPages() {                                                               
1427         // Post the remaining side pages to be loaded                                                    
1428         if (!mDeferredBindRunnables.isEmpty()) {                                                         
1429             Runnable[] deferredBindRunnables = null;                                                     
1430             synchronized (mDeferredBindRunnables) {                                                      
1431                 deferredBindRunnables = mDeferredBindRunnables.toArray(                                  
1432                         new Runnable[mDeferredBindRunnables.size()]);                                    
1433                 mDeferredBindRunnables.clear();                                                          
1434             }                                                                                            
1435             for (final Runnable r : deferredBindRunnables) {                                             
1436                 mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);                                          
1437             }                                                                                            
1438         }                                                                                                
1439     }                                                                                                    
1440                                                                                                          
1441     public void stopLoader() {                                                                           
1442         synchronized (mLock) {                                                                           
1443             if (mLoaderTask != null) {                                                                   
1444                 mLoaderTask.stopLocked();                                                                
1445             }                                                                                            
1446         }                                                                                                
1447     }                                                                                                    
1448                                                                                                          
1449     /** Loads the workspace screens db into a map of Rank -> ScreenId */                                 
1450     private static TreeMap<Integer, Long> loadWorkspaceScreensDb(Context context) {                      
1451         final ContentResolver contentResolver = context.getContentResolver();                            
1452         final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                            
1453         final Cursor sc = contentResolver.query(screensUri, null, null, null, null);                     
1454         TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();                            
1455                                                                                                          
1456         try {                                                                                            
1457             final int idIndex = sc.getColumnIndexOrThrow(                                                
1458                     LauncherSettings.WorkspaceScreens._ID);                                              
1459             final int rankIndex = sc.getColumnIndexOrThrow(                                              
1460                     LauncherSettings.WorkspaceScreens.SCREEN_RANK);                                      
1461             while (sc.moveToNext()) {                                                                    
1462                 try {                                                                                    
1463                     long screenId = sc.getLong(idIndex);                                                 
1464                     int rank = sc.getInt(rankIndex);                                                     
1465                     orderedScreens.put(rank, screenId);                                                  
1466                 } catch (Exception e) {                                                                  
1467                     Launcher.addDumpLog(TAG, "Desktop items loading interrupted - invalid screens: " + e,🔵
1468                 }                                                                                        
1469             }                                                                                            
1470         } finally {                                                                                      
1471             sc.close();                                                                                  
1472         }                                                                                                
1473                                                                                                          
1474         // Log to disk                                                                                   
1475         Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);                           
1476         ArrayList<String> orderedScreensPairs= new ArrayList<String>();                                  
1477         for (Integer i : orderedScreens.keySet()) {                                                      
1478             orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }");                     
1479         }                                                                                                
1480         Launcher.addDumpLog(TAG, "11683562 -   screens: " +                                              
1481                 TextUtils.join(", ", orderedScreensPairs), true);                                        
1482         return orderedScreens;                                                                           
1483     }                                                                                                    
1484                                                                                                          
1485     public boolean isAllAppsLoaded() {                                                                   
1486         return mAllAppsLoaded;                                                                           
1487     }                                                                                                    
1488                                                                                                          
1489     boolean isLoadingWorkspace() {                                                                       
1490         synchronized (mLock) {                                                                           
1491             if (mLoaderTask != null) {                                                                   
1492                 return mLoaderTask.isLoadingWorkspace();                                                 
1493             }                                                                                            
1494         }                                                                                                
1495         return false;                                                                                    
1496     }                                                                                                    
1497                                                                                                          
1498     /**                                                                                                  
1499      * Runnable for the thread that loads the contents of the launcher:                                  
1500      *   - workspace icons                                                                               
1501      *   - widgets                                                                                       
1502      *   - all apps icons                                                                                
1503      */                                                                                                  
1504     private class LoaderTask implements Runnable {                                                       
1505         private Context mContext;                                                                        
1506         private boolean mIsLaunching;                                                                    
1507         private boolean mIsLoadingAndBindingWorkspace;                                                   
1508         private boolean mStopped;                                                                        
1509         private boolean mLoadAndBindStepFinished;                                                        
1510         private int mFlags;                                                                              
1511                                                                                                          
1512         private HashMap<Object, CharSequence> mLabelCache;                                               
1513                                                                                                          
1514         LoaderTask(Context context, boolean isLaunching, int flags) {                                    
1515             mContext = context;                                                                          
1516             mIsLaunching = isLaunching;                                                                  
1517             mLabelCache = new HashMap<Object, CharSequence>();                                           
1518             mFlags = flags;                                                                              
1519         }                                                                                                
1520                                                                                                          
1521         boolean isLaunching() {                                                                          
1522             return mIsLaunching;                                                                         
1523         }                                                                                                
1524                                                                                                          
1525         boolean isLoadingWorkspace() {                                                                   
1526             return mIsLoadingAndBindingWorkspace;                                                        
1527         }                                                                                                
1528                                                                                                          
1529         /** Returns whether this is an upgrade path */                                                   
1530         private boolean loadAndBindWorkspace() {                                                         
1531             mIsLoadingAndBindingWorkspace = true;                                                        
1532                                                                                                          
1533             // Load the workspace                                                                        
1534             if (DEBUG_LOADERS) {                                                                         
1535                 Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);                 
1536             }                                                                                            
1537                                                                                                          
1538             boolean isUpgradePath = false;                                                               
1539             if (!mWorkspaceLoaded) {                                                                     
1540                 isUpgradePath = loadWorkspace();                                                         
1541                 synchronized (LoaderTask.this) {                                                         
1542                     if (mStopped) {                                                                      
1543                         return isUpgradePath;                                                            
1544                     }                                                                                    
1545                     mWorkspaceLoaded = true;                                                             
1546                 }                                                                                        
1547             }                                                                                            
1548                                                                                                          
1549             // Bind the workspace                                                                        
1550             bindWorkspace(-1, isUpgradePath);                                                            
1551             return isUpgradePath;                                                                        
1552         }                                                                                                
1553                                                                                                          
1554         private void waitForIdle() {                                                                     
1555             // Wait until the either we're stopped or the other threads are done.                        
1556             // This way we don't start loading all apps until the workspace has settled                  
1557             // down.                                                                                     
1558             synchronized (LoaderTask.this) {                                                             
1559                 final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;           
1560                                                                                                          
1561                 mHandler.postIdle(new Runnable() {                                                       
1562                         public void run() {                                                              
1563                             synchronized (LoaderTask.this) {                                             
1564                                 mLoadAndBindStepFinished = true;                                         
1565                                 if (DEBUG_LOADERS) {                                                     
1566                                     Log.d(TAG, "done with previous binding step");                       
1567                                 }                                                                        
1568                                 LoaderTask.this.notify();                                                
1569                             }                                                                            
1570                         }                                                                                
1571                     });                                                                                  
1572                                                                                                          
1573                 while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) {               
1574                     try {                                                                                
1575                         // Just in case mFlushingWorkerThread changes but we aren't woken up,            
1576                         // wait no longer than 1sec at a time                                            
1577                         this.wait(1000);                                                                 
1578                     } catch (InterruptedException ex) {                                                  
1579                         // Ignore                                                                        
1580                     }                                                                                    
1581                 }                                                                                        
1582                 if (DEBUG_LOADERS) {                                                                     
1583                     Log.d(TAG, "waited "                                                                 
1584                             + (SystemClock.uptimeMillis()-workspaceWaitTime)                             
1585                             + "ms for previous step to finish binding");                                 
1586                 }                                                                                        
1587             }                                                                                            
1588         }                                                                                                
1589                                                                                                          
1590         void runBindSynchronousPage(int synchronousBindPage) {                                           
1591             if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {                                 
1592                 // Ensure that we have a valid page index to load synchronously                          
1593                 throw new RuntimeException("Should not call runBindSynchronousPage() without " +         
1594                         "valid page index");                                                             
1595             }                                                                                            
1596             if (!mAllAppsLoaded || !mWorkspaceLoaded) {                                                  
1597                 // Ensure that we don't try and bind a specified page when the pages have not been       
1598                 // loaded already (we should load everything asynchronously in that case)                
1599                 throw new RuntimeException("Expecting AllApps and Workspace to be loaded");              
1600             }                                                                                            
1601             synchronized (mLock) {                                                                       
1602                 if (mIsLoaderTaskRunning) {                                                              
1603                     // Ensure that we are never running the background loading at this point since       
1604                     // we also touch the background collections                                          
1605                     throw new RuntimeException("Error! Background loading is already running");          
1606                 }                                                                                        
1607             }                                                                                            
1608                                                                                                          
1609             // XXX: Throw an exception if we are already loading (since we touch the worker thread       
1610             //      data structures, we can't allow any other thread to touch that data, but because     
1611             //      this call is synchronous, we can get away with not locking).                         
1612                                                                                                          
1613             // The LauncherModel is static in the LauncherAppState and mHandler may have queued          
1614             // operations from the previous activity.  We need to ensure that all queued operations      
1615             // are executed before any synchronous binding work is done.                                 
1616             mHandler.flush();                                                                            
1617                                                                                                          
1618             // Divide the set of loaded items into those that we are binding synchronously, and          
1619             // everything else that is to be bound normally (asynchronously).                            
1620             bindWorkspace(synchronousBindPage, false);                                                   
1621             // XXX: For now, continue posting the binding of AllApps as there are other issues that      
1622             //      arise from that.                                                                     
1623             onlyBindAllApps();                                                                           
1624         }                                                                                                
1625                                                                                                          
1626         public void run() {                                                                              
1627             boolean isUpgrade = false;                                                                   
1628                                                                                                          
1629             synchronized (mLock) {                                                                       
1630                 mIsLoaderTaskRunning = true;                                                             
1631             }                                                                                            
1632             // Optimize for end-user experience: if the Launcher is up and // running with the           
1633             // All Apps interface in the foreground, load All Apps first. Otherwise, load the            
1634             // workspace first (default).                                                                
1635             keep_running: {                                                                              
1636                 // Elevate priority when Home launches for the first time to avoid                       
1637                 // starving at boot time. Staring at a blank home is not cool.                           
1638                 synchronized (mLock) {                                                                   
1639                     if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +                        
1640                             (mIsLaunching ? "DEFAULT" : "BACKGROUND"));                                  
1641                     android.os.Process.setThreadPriority(mIsLaunching                                    
1642                             ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);     
1643                 }                                                                                        
1644                 if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");                              
1645                 isUpgrade = loadAndBindWorkspace();                                                      
1646                                                                                                          
1647                 if (mStopped) {                                                                          
1648                     break keep_running;                                                                  
1649                 }                                                                                        
1650                                                                                                          
1651                 // Whew! Hard work done.  Slow us down, and wait until the UI thread has                 
1652                 // settled down.                                                                         
1653                 synchronized (mLock) {                                                                   
1654                     if (mIsLaunching) {                                                                  
1655                         if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");          
1656                         android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);        
1657                     }                                                                                    
1658                 }                                                                                        
1659                 waitForIdle();                                                                           
1660                                                                                                          
1661                 // second step                                                                           
1662                 if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");                               
1663                 loadAndBindAllApps();                                                                    
1664                                                                                                          
1665                 // Restore the default thread priority after we are done loading items                   
1666                 synchronized (mLock) {                                                                   
1667                     android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);               
1668                 }                                                                                        
1669             }                                                                                            
1670                                                                                                          
1671             // Update the saved icons if necessary                                                       
1672             if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");                   
1673             synchronized (sBgLock) {                                                                     
1674                 for (Object key : sBgDbIconCache.keySet()) {                                             
1675                     updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));              
1676                 }                                                                                        
1677                 sBgDbIconCache.clear();                                                                  
1678             }                                                                                            
1679                                                                                                          
1680             if (LauncherAppState.isDisableAllApps()) {                                                   
1681                 // Ensure that all the applications that are in the system are                           
1682                 // represented on the home screen.                                                       
1683                 if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {                                       
1684                     verifyApplications();                                                                
1685                 }                                                                                        
1686             }                                                                                            
1687                                                                                                          
1688             // Clear out this reference, otherwise we end up holding it until all of the                 
1689             // callback runnables are done.                                                              
1690             mContext = null;                                                                             
1691                                                                                                          
1692             synchronized (mLock) {                                                                       
1693                 // If we are still the last one to be scheduled, remove ourselves.                       
1694                 if (mLoaderTask == this) {                                                               
1695                     mLoaderTask = null;                                                                  
1696                 }                                                                                        
1697                 mIsLoaderTaskRunning = false;                                                            
1698             }                                                                                            
1699         }                                                                                                
1700                                                                                                          
1701         public void stopLocked() {                                                                       
1702             synchronized (LoaderTask.this) {                                                             
1703                 mStopped = true;                                                                         
1704                 this.notify();                                                                           
1705             }                                                                                            
1706         }                                                                                                
1707                                                                                                          
1708         /**                                                                                              
1709          * Gets the callbacks object.  If we've been stopped, or if the launcher object                  
1710          * has somehow been garbage collected, return null instead.  Pass in the Callbacks               
1711          * object that was around when the deferred message was scheduled, and if there's                
1712          * a new Callbacks object around then also return null.  This will save us from                  
1713          * calling onto it with data that will be ignored.                                               
1714          */                                                                                              
1715         Callbacks tryGetCallbacks(Callbacks oldCallbacks) {                                              
1716             synchronized (mLock) {                                                                       
1717                 if (mStopped) {                                                                          
1718                     return null;                                                                         
1719                 }                                                                                        
1720                                                                                                          
1721                 if (mCallbacks == null) {                                                                
1722                     return null;                                                                         
1723                 }                                                                                        
1724                                                                                                          
1725                 final Callbacks callbacks = mCallbacks.get();                                            
1726                 if (callbacks != oldCallbacks) {                                                         
1727                     return null;                                                                         
1728                 }                                                                                        
1729                 if (callbacks == null) {                                                                 
1730                     Log.w(TAG, "no mCallbacks");                                                         
1731                     return null;                                                                         
1732                 }                                                                                        
1733                                                                                                          
1734                 return callbacks;                                                                        
1735             }                                                                                            
1736         }                                                                                                
1737                                                                                                          
1738         private void verifyApplications() {                                                              
1739             final Context context = mApp.getContext();                                                   
1740                                                                                                          
1741             // Cross reference all the applications in our apps list with items in the workspace         
1742             ArrayList<ItemInfo> tmpInfos;                                                                
1743             ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();                                       
1744             synchronized (sBgLock) {                                                                     
1745                 for (AppInfo app : mBgAllAppsList.data) {                                                
1746                     tmpInfos = getItemInfoForComponentName(app.componentName, app.user);                 
1747                     if (tmpInfos.isEmpty()) {                                                            
1748                         // We are missing an application icon, so add this to the workspace              
1749                         added.add(app);                                                                  
1750                         // This is a rare event, so lets log it                                          
1751                         Log.e(TAG, "Missing Application on load: " + app);                               
1752                     }                                                                                    
1753                 }                                                                                        
1754             }                                                                                            
1755             if (!added.isEmpty()) {                                                                      
1756                 addAndBindAddedWorkspaceApps(context, added);                                            
1757             }                                                                                            
1758         }                                                                                                
1759                                                                                                          
1760         // check & update map of what's occupied; used to discard overlapping/invalid items              
1761         private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,          
1762                                            AtomicBoolean deleteOnInvalidPlacement) {                     
1763             LauncherAppState app = LauncherAppState.getInstance();                                       
1764             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
1765             final int countX = (int) grid.numColumns;                                                    
1766             final int countY = (int) grid.numRows;                                                       
1767                                                                                                          
1768             long containerIndex = item.screenId;                                                         
1769             if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                        
1770                 // Return early if we detect that an item is under the hotseat button                    
1771                 if (mCallbacks == null ||                                                                
1772                         mCallbacks.get().isAllAppsButtonRank((int) item.screenId)) {                     
1773                     deleteOnInvalidPlacement.set(true);                                                  
1774                     Log.e(TAG, "Error loading shortcut into hotseat " + item                             
1775                             + " into position (" + item.screenId + ":" + item.cellX + ","                
1776                             + item.cellY + ") occupied by all apps");                                    
1777                     return false;                                                                        
1778                 }                                                                                        
1779                                                                                                          
1780                 final ItemInfo[][] hotseatItems =                                                        
1781                         occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);               
1782                                                                                                          
1783                 if (item.screenId >= grid.numHotseatIcons) {                                             
1784                     Log.e(TAG, "Error loading shortcut " + item                                          
1785                             + " into hotseat position " + item.screenId                                  
1786                             + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)            
1787                             + ")");                                                                      
1788                     return false;                                                                        
1789                 }                                                                                        
1790                                                                                                          
1791                 if (hotseatItems != null) {                                                              
1792                     if (hotseatItems[(int) item.screenId][0] != null) {                                  
1793                         Log.e(TAG, "Error loading shortcut into hotseat " + item                         
1794                                 + " into position (" + item.screenId + ":" + item.cellX + ","            
1795                                 + item.cellY + ") occupied by "                                          
1796                                 + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)             
1797                                 [(int) item.screenId][0]);                                               
1798                             return false;                                                                
1799                     } else {                                                                             
1800                         hotseatItems[(int) item.screenId][0] = item;                                     
1801                         return true;                                                                     
1802                     }                                                                                    
1803                 } else {                                                                                 
1804                     final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];              
1805                     items[(int) item.screenId][0] = item;                                                
1806                     occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);            
1807                     return true;                                                                         
1808                 }                                                                                        
1809             } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {                 
1810                 // Skip further checking if it is not the hotseat or workspace container                 
1811                 return true;                                                                             
1812             }                                                                                            
1813                                                                                                          
1814             if (!occupied.containsKey(item.screenId)) {                                                  
1815                 ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];                               
1816                 occupied.put(item.screenId, items);                                                      
1817             }                                                                                            
1818                                                                                                          
1819             final ItemInfo[][] screens = occupied.get(item.screenId);                                    
1820             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                        
1821                     item.cellX < 0 || item.cellY < 0 ||                                                  
1822                     item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {              
1823                 Log.e(TAG, "Error loading shortcut " + item                                              
1824                         + " into cell (" + containerIndex + "-" + item.screenId + ":"                    
1825                         + item.cellX + "," + item.cellY                                                  
1826                         + ") out of screen bounds ( " + countX + "x" + countY + ")");                    
1827                 return false;                                                                            
1828             }                                                                                            
1829                                                                                                          
1830             // Check if any workspace icons overlap with each other                                      
1831             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                 
1832                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                             
1833                     if (screens[x][y] != null) {                                                         
1834                         Log.e(TAG, "Error loading shortcut " + item                                      
1835                             + " into cell (" + containerIndex + "-" + item.screenId + ":"                
1836                             + x + "," + y                                                                
1837                             + ") occupied by "                                                           
1838                             + screens[x][y]);                                                            
1839                         return false;                                                                    
1840                     }                                                                                    
1841                 }                                                                                        
1842             }                                                                                            
1843             for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                 
1844                 for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                             
1845                     screens[x][y] = item;                                                                
1846                 }                                                                                        
1847             }                                                                                            
1848                                                                                                          
1849             return true;                                                                                 
1850         }                                                                                                
1851                                                                                                          
1852         /** Clears all the sBg data structures */                                                        
1853         private void clearSBgDataStructures() {                                                          
1854             synchronized (sBgLock) {                                                                     
1855                 sBgWorkspaceItems.clear();                                                               
1856                 sBgAppWidgets.clear();                                                                   
1857                 sBgFolders.clear();                                                                      
1858                 sBgItemsIdMap.clear();                                                                   
1859                 sBgDbIconCache.clear();                                                                  
1860                 sBgWorkspaceScreens.clear();                                                             
1861             }                                                                                            
1862         }                                                                                                
1863                                                                                                          
1864         /** Returns whether this is an upgrade path */                                                   
1865         private boolean loadWorkspace() {                                                                
1866             // Log to disk                                                                               
1867             Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);                                
1868                                                                                                          
1869             final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                               
1870                                                                                                          
1871             final Context context = mContext;                                                            
1872             final ContentResolver contentResolver = context.getContentResolver();                        
1873             final PackageManager manager = context.getPackageManager();                                  
1874             final AppWidgetManager widgets = AppWidgetManager.getInstance(context);                      
1875             final boolean isSafeMode = manager.isSafeMode();                                             
1876             final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);             
1877             final boolean isSdCardReady = context.registerReceiver(null,                                 
1878                     new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;                             
1879                                                                                                          
1880             LauncherAppState app = LauncherAppState.getInstance();                                       
1881             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
1882             int countX = (int) grid.numColumns;                                                          
1883             int countY = (int) grid.numRows;                                                             
1884                                                                                                          
1885             if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {                                           
1886                 Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);            
1887                 LauncherAppState.getLauncherProvider().deleteDatabase();                                 
1888             }                                                                                            
1889                                                                                                          
1890             if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {                                         
1891                 // append the user's Launcher2 shortcuts                                                 
1892                 Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);               
1893                 LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();                      
1894             } else {                                                                                     
1895                 // Make sure the default workspace is loaded                                             
1896                 Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);             
1897                 LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();                
1898             }                                                                                            
1899                                                                                                          
1900             // This code path is for our old migration code and should no longer be exercised            
1901             boolean loadedOldDb = false;                                                                 
1902                                                                                                          
1903             // Log to disk                                                                               
1904             Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);                  
1905                                                                                                          
1906             synchronized (sBgLock) {                                                                     
1907                 clearSBgDataStructures();                                                                
1908                 final HashSet<String> installingPkgs = PackageInstallerCompat                            
1909                         .getInstance(mContext).updateAndGetActiveSessionCache();                         
1910                                                                                                          
1911                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();                             
1912                 final ArrayList<Long> restoredRows = new ArrayList<Long>();                              
1913                 final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;           
1914                 if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);                       
1915                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);              
1916                                                                                                          
1917                 // +1 for the hotseat (it can be larger than the workspace)                              
1918                 // Load workspace in reverse order to ensure that latest items are loaded first (and     
1919                 // before any earlier duplicates)                                                        
1920                 final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();          
1921                                                                                                          
1922                 try {                                                                                    
1923                     final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);         
1924                     final int intentIndex = c.getColumnIndexOrThrow                                      
1925                             (LauncherSettings.Favorites.INTENT);                                         
1926                     final int titleIndex = c.getColumnIndexOrThrow                                       
1927                             (LauncherSettings.Favorites.TITLE);                                          
1928                     final int iconTypeIndex = c.getColumnIndexOrThrow(                                   
1929                             LauncherSettings.Favorites.ICON_TYPE);                                       
1930                     final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);      
1931                     final int iconPackageIndex = c.getColumnIndexOrThrow(                                
1932                             LauncherSettings.Favorites.ICON_PACKAGE);                                    
1933                     final int iconResourceIndex = c.getColumnIndexOrThrow(                               
1934                             LauncherSettings.Favorites.ICON_RESOURCE);                                   
1935                     final int containerIndex = c.getColumnIndexOrThrow(                                  
1936                             LauncherSettings.Favorites.CONTAINER);                                       
1937                     final int itemTypeIndex = c.getColumnIndexOrThrow(                                   
1938                             LauncherSettings.Favorites.ITEM_TYPE);                                       
1939                     final int appWidgetIdIndex = c.getColumnIndexOrThrow(                                
1940                             LauncherSettings.Favorites.APPWIDGET_ID);                                    
1941                     final int appWidgetProviderIndex = c.getColumnIndexOrThrow(                          
1942                             LauncherSettings.Favorites.APPWIDGET_PROVIDER);                              
1943                     final int screenIndex = c.getColumnIndexOrThrow(                                     
1944                             LauncherSettings.Favorites.SCREEN);                                          
1945                     final int cellXIndex = c.getColumnIndexOrThrow                                       
1946                             (LauncherSettings.Favorites.CELLX);                                          
1947                     final int cellYIndex = c.getColumnIndexOrThrow                                       
1948                             (LauncherSettings.Favorites.CELLY);                                          
1949                     final int spanXIndex = c.getColumnIndexOrThrow                                       
1950                             (LauncherSettings.Favorites.SPANX);                                          
1951                     final int spanYIndex = c.getColumnIndexOrThrow(                                      
1952                             LauncherSettings.Favorites.SPANY);                                           
1953                     final int restoredIndex = c.getColumnIndexOrThrow(                                   
1954                             LauncherSettings.Favorites.RESTORED);                                        
1955                     final int profileIdIndex = c.getColumnIndexOrThrow(                                  
1956                             LauncherSettings.Favorites.PROFILE_ID);                                      
1957                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);      
1958                     //final int displayModeIndex = c.getColumnIndexOrThrow(                              
1959                     //        LauncherSettings.Favorites.DISPLAY_MODE);                                  
1960                                                                                                          
1961                     ShortcutInfo info;                                                                   
1962                     String intentDescription;                                                            
1963                     LauncherAppWidgetInfo appWidgetInfo;                                                 
1964                     int container;                                                                       
1965                     long id;                                                                             
1966                     Intent intent;                                                                       
1967                     UserHandleCompat user;                                                               
1968                                                                                                          
1969                     while (!mStopped && c.moveToNext()) {                                                
1970                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);               
1971                         try {                                                                            
1972                             int itemType = c.getInt(itemTypeIndex);                                      
1973                             boolean restored = 0 != c.getInt(restoredIndex);                             
1974                             boolean allowMissingTarget = false;                                          
1975                                                                                                          
1976                             switch (itemType) {                                                          
1977                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                       
1978                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                          
1979                                 id = c.getLong(idIndex);                                                 
1980                                 intentDescription = c.getString(intentIndex);                            
1981                                 long serialNumber = c.getInt(profileIdIndex);                            
1982                                 user = mUserManager.getUserForSerialNumber(serialNumber);                
1983                                 int promiseType = c.getInt(restoredIndex);                               
1984                                 if (user == null) {                                                      
1985                                     // User has been deleted remove the item.                            
1986                                     itemsToRemove.add(id);                                               
1987                                     continue;                                                            
1988                                 }                                                                        
1989                                 try {                                                                    
1990                                     intent = Intent.parseUri(intentDescription, 0);                      
1991                                     ComponentName cn = intent.getComponent();                            
1992                                     if (cn != null && cn.getPackageName() != null) {                     
1993                                         boolean validPkg = launcherApps.isPackageEnabledForProfile(      
1994                                                 cn.getPackageName(), user);                              
1995                                         boolean validComponent = validPkg &&                             
1996                                                 launcherApps.isActivityEnabledForProfile(cn, user);      
1997                                                                                                          
1998                                         if (validComponent) {                                            
1999                                             if (restored) {                                              
2000                                                 // no special handling necessary for this item           
2001                                                 restoredRows.add(id);                                    
2002                                                 restored = false;                                        
2003                                             }                                                            
2004                                         } else if (validPkg) {                                           
2005                                             intent = null;                                               
2006                                             if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
2007                                                 // We allow auto install apps to have their intent       
2008                                                 // updated after an install.                             
2009                                                 intent = manager.getLaunchIntentForPackage(              
2010                                                         cn.getPackageName());                            
2011                                                 if (intent != null) {                                    
2012                                                     ContentValues values = new ContentValues();          
2013                                                     values.put(LauncherSettings.Favorites.INTENT,        
2014                                                             intent.toUri(0));                            
2015                                                     String where = BaseColumns._ID + "= ?";              
2016                                                     String[] args = {Long.toString(id)};                 
2017                                                     contentResolver.update(contentUri, values, where, arg🔵
2018                                                 }                                                        
2019                                             }                                                            
2020                                                                                                          
2021                                             if (intent == null) {                                        
2022                                                 // The app is installed but the component is no          
2023                                                 // longer available.                                     
2024                                                 Launcher.addDumpLog(TAG,                                 
2025                                                         "Invalid component removed: " + cn, true);       
2026                                                 itemsToRemove.add(id);                                   
2027                                                 continue;                                                
2028                                             } else {                                                     
2029                                                 // no special handling necessary for this item           
2030                                                 restoredRows.add(id);                                    
2031                                                 restored = false;                                        
2032                                             }                                                            
2033                                         } else if (restored) {                                           
2034                                             // Package is not yet available but might be                 
2035                                             // installed later.                                          
2036                                             Launcher.addDumpLog(TAG,                                     
2037                                                     "package not yet restored: " + cn, true);            
2038                                                                                                          
2039                                             if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
2040                                                 // Restore has started once.                             
2041                                             } else if (installingPkgs.contains(cn.getPackageName())) {   
2042                                                 // App restore has started. Update the flag              
2043                                                 promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;        
2044                                                 ContentValues values = new ContentValues();              
2045                                                 values.put(LauncherSettings.Favorites.RESTORED,          
2046                                                         promiseType);                                    
2047                                                 String where = BaseColumns._ID + "= ?";                  
2048                                                 String[] args = {Long.toString(id)};                     
2049                                                 contentResolver.update(contentUri, values, where, args); 
2050                                                                                                          
2051                                             } else if (REMOVE_UNRESTORED_ICONS) {                        
2052                                                 Launcher.addDumpLog(TAG,                                 
2053                                                         "Unrestored package removed: " + cn, true);      
2054                                                 itemsToRemove.add(id);                                   
2055                                                 continue;                                                
2056                                             }                                                            
2057                                         } else if (isSdCardReady) {                                      
2058                                             // Do not wait for external media load anymore.              
2059                                             // Log the invalid package, and remove it                    
2060                                             Launcher.addDumpLog(TAG,                                     
2061                                                     "Invalid package removed: " + cn, true);             
2062                                             itemsToRemove.add(id);                                       
2063                                             continue;                                                    
2064                                         } else {                                                         
2065                                             // SdCard is not ready yet. Package might get available,     
2066                                             // once it is ready.                                         
2067                                             Launcher.addDumpLog(TAG, "Invalid package: " + cn            
2068                                                     + " (check again later)", true);                     
2069                                             HashSet<String> pkgs = sPendingPackages.get(user);           
2070                                             if (pkgs == null) {                                          
2071                                                 pkgs = new HashSet<String>();                            
2072                                                 sPendingPackages.put(user, pkgs);                        
2073                                             }                                                            
2074                                             pkgs.add(cn.getPackageName());                               
2075                                             allowMissingTarget = true;                                   
2076                                             // Add the icon on the workspace anyway.                     
2077                                         }                                                                
2078                                     } else if (cn == null) {                                             
2079                                         // For shortcuts with no component, keep them as they are        
2080                                         restoredRows.add(id);                                            
2081                                         restored = false;                                                
2082                                     }                                                                    
2083                                 } catch (URISyntaxException e) {                                         
2084                                     Launcher.addDumpLog(TAG,                                             
2085                                             "Invalid uri: " + intentDescription, true);                  
2086                                     continue;                                                            
2087                                 }                                                                        
2088                                                                                                          
2089                                 if (restored) {                                                          
2090                                     if (user.equals(UserHandleCompat.myUserHandle())) {                  
2091                                         Launcher.addDumpLog(TAG,                                         
2092                                                 "constructing info for partially restored package",      
2093                                                 true);                                                   
2094                                         info = getRestoredItemInfo(c, titleIndex, intent, promiseType);  
2095                                         intent = getRestoredItemIntent(c, context, intent);              
2096                                     } else {                                                             
2097                                         // Don't restore items for other profiles.                       
2098                                         itemsToRemove.add(id);                                           
2099                                         continue;                                                        
2100                                     }                                                                    
2101                                 } else if (itemType ==                                                   
2102                                         LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {              
2103                                     info = getShortcutInfo(manager, intent, user, context, c,            
2104                                             iconIndex, titleIndex, mLabelCache, allowMissingTarget);     
2105                                 } else {                                                                 
2106                                     info = getShortcutInfo(c, context, iconTypeIndex,                    
2107                                             iconPackageIndex, iconResourceIndex, iconIndex,              
2108                                             titleIndex);                                                 
2109                                                                                                          
2110                                     // App shortcuts that used to be automatically added to Launcher     
2111                                     // didn't always have the correct intent flags set, so do that       
2112                                     // here                                                              
2113                                     if (intent.getAction() != null &&                                    
2114                                         intent.getCategories() != null &&                                
2115                                         intent.getAction().equals(Intent.ACTION_MAIN) &&                 
2116                                         intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {     
2117                                         intent.addFlags(                                                 
2118                                             Intent.FLAG_ACTIVITY_NEW_TASK |                              
2119                                             Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);                  
2120                                     }                                                                    
2121                                 }                                                                        
2122                                                                                                          
2123                                 if (info != null) {                                                      
2124                                     info.id = id;                                                        
2125                                     info.intent = intent;                                                
2126                                     container = c.getInt(containerIndex);                                
2127                                     info.container = container;                                          
2128                                     info.screenId = c.getInt(screenIndex);                               
2129                                     info.cellX = c.getInt(cellXIndex);                                   
2130                                     info.cellY = c.getInt(cellYIndex);                                   
2131                                     info.spanX = 1;                                                      
2132                                     info.spanY = 1;                                                      
2133                                     info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);          
2134                                     info.isDisabled = isSafeMode                                         
2135                                             && !Utilities.isSystemApp(context, intent);                  
2136                                                                                                          
2137                                     // check & update map of what's occupied                             
2138                                     deleteOnInvalidPlacement.set(false);                                 
2139                                     if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) { 
2140                                         if (deleteOnInvalidPlacement.get()) {                            
2141                                             itemsToRemove.add(id);                                       
2142                                         }                                                                
2143                                         break;                                                           
2144                                     }                                                                    
2145                                                                                                          
2146                                     switch (container) {                                                 
2147                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
2148                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
2149                                         sBgWorkspaceItems.add(info);                                     
2150                                         break;                                                           
2151                                     default:                                                             
2152                                         // Item is in a user folder                                      
2153                                         FolderInfo folderInfo =                                          
2154                                                 findOrMakeFolder(sBgFolders, container);                 
2155                                         folderInfo.add(info);                                            
2156                                         break;                                                           
2157                                     }                                                                    
2158                                     sBgItemsIdMap.put(info.id, info);                                    
2159                                                                                                          
2160                                     // now that we've loaded everthing re-save it with the               
2161                                     // icon in case it disappears somehow.                               
2162                                     queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);            
2163                                 } else {                                                                 
2164                                     throw new RuntimeException("Unexpected null ShortcutInfo");          
2165                                 }                                                                        
2166                                 break;                                                                   
2167                                                                                                          
2168                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                            
2169                                 id = c.getLong(idIndex);                                                 
2170                                 FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);                
2171                                                                                                          
2172                                 folderInfo.title = c.getString(titleIndex);                              
2173                                 folderInfo.id = id;                                                      
2174                                 container = c.getInt(containerIndex);                                    
2175                                 folderInfo.container = container;                                        
2176                                 folderInfo.screenId = c.getInt(screenIndex);                             
2177                                 folderInfo.cellX = c.getInt(cellXIndex);                                 
2178                                 folderInfo.cellY = c.getInt(cellYIndex);                                 
2179                                 folderInfo.spanX = 1;                                                    
2180                                 folderInfo.spanY = 1;                                                    
2181                                                                                                          
2182                                 // check & update map of what's occupied                                 
2183                                 deleteOnInvalidPlacement.set(false);                                     
2184                                 if (!checkItemPlacement(occupied, folderInfo,                            
2185                                         deleteOnInvalidPlacement)) {                                     
2186                                     if (deleteOnInvalidPlacement.get()) {                                
2187                                         itemsToRemove.add(id);                                           
2188                                     }                                                                    
2189                                     break;                                                               
2190                                 }                                                                        
2191                                                                                                          
2192                                 switch (container) {                                                     
2193                                     case LauncherSettings.Favorites.CONTAINER_DESKTOP:                   
2194                                     case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                   
2195                                         sBgWorkspaceItems.add(folderInfo);                               
2196                                         break;                                                           
2197                                 }                                                                        
2198                                                                                                          
2199                                 if (restored) {                                                          
2200                                     // no special handling required for restored folders                 
2201                                     restoredRows.add(id);                                                
2202                                 }                                                                        
2203                                                                                                          
2204                                 sBgItemsIdMap.put(folderInfo.id, folderInfo);                            
2205                                 sBgFolders.put(folderInfo.id, folderInfo);                               
2206                                 break;                                                                   
2207                                                                                                          
2208                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                         
2209                                 // Read all Launcher-specific widget details                             
2210                                 int appWidgetId = c.getInt(appWidgetIdIndex);                            
2211                                 String savedProvider = c.getString(appWidgetProviderIndex);              
2212                                 id = c.getLong(idIndex);                                                 
2213                                 final ComponentName component =                                          
2214                                         ComponentName.unflattenFromString(savedProvider);                
2215                                                                                                          
2216                                 final int restoreStatus = c.getInt(restoredIndex);                       
2217                                 final boolean isIdValid = (restoreStatus &                               
2218                                         LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;                   
2219                                                                                                          
2220                                 final boolean wasProviderReady = (restoreStatus &                        
2221                                         LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;             
2222                                                                                                          
2223                                 final AppWidgetProviderInfo provider = isIdValid                         
2224                                         ? widgets.getAppWidgetInfo(appWidgetId)                          
2225                                         : findAppWidgetProviderInfoWithComponent(context, component);    
2226                                                                                                          
2227                                 final boolean isProviderReady = isValidProvider(provider);               
2228                                 if (!isSafeMode && wasProviderReady && !isProviderReady) {               
2229                                     String log = "Deleting widget that isn't installed anymore: "        
2230                                             + "id=" + id + " appWidgetId=" + appWidgetId;                
2231                                     Log.e(TAG, log);                                                     
2232                                     Launcher.addDumpLog(TAG, log, false);                                
2233                                     itemsToRemove.add(id);                                               
2234                                 } else {                                                                 
2235                                     if (isProviderReady) {                                               
2236                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,           
2237                                                 provider.provider);                                      
2238                                         int[] minSpan =                                                  
2239                                                 Launcher.getMinSpanForWidget(context, provider);         
2240                                         appWidgetInfo.minSpanX = minSpan[0];                             
2241                                         appWidgetInfo.minSpanY = minSpan[1];                             
2242                                                                                                          
2243                                         int status = restoreStatus;                                      
2244                                         if (!wasProviderReady) {                                         
2245                                             // If provider was not previously ready, update the          
2246                                             // status and UI flag.                                       
2247                                                                                                          
2248                                             // Id would be valid only if the widget restore broadcast was🔵
2249                                             if (isIdValid) {                                             
2250                                                 status = LauncherAppWidgetInfo.RESTORE_COMPLETED;        
2251                                             } else {                                                     
2252                                                 status &= ~LauncherAppWidgetInfo                         
2253                                                         .FLAG_PROVIDER_NOT_READY;                        
2254                                             }                                                            
2255                                         }                                                                
2256                                         appWidgetInfo.restoreStatus = status;                            
2257                                     } else {                                                             
2258                                         Log.v(TAG, "Widget restore pending id=" + id                     
2259                                                 + " appWidgetId=" + appWidgetId                          
2260                                                 + " status =" + restoreStatus);                          
2261                                         appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,           
2262                                                 component);                                              
2263                                         appWidgetInfo.restoreStatus = restoreStatus;                     
2264                                                                                                          
2265                                         if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) 🔵
2266                                             // Restore has started once.                                 
2267                                         } else if (installingPkgs.contains(component.getPackageName())) {
2268                                             // App restore has started. Update the flag                  
2269                                             appWidgetInfo.restoreStatus |=                               
2270                                                     LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;          
2271                                         } else if (REMOVE_UNRESTORED_ICONS) {                            
2272                                             Launcher.addDumpLog(TAG,                                     
2273                                                     "Unrestored widget removed: " + component, true);    
2274                                             itemsToRemove.add(id);                                       
2275                                             continue;                                                    
2276                                         }                                                                
2277                                     }                                                                    
2278                                                                                                          
2279                                     appWidgetInfo.id = id;                                               
2280                                     appWidgetInfo.screenId = c.getInt(screenIndex);                      
2281                                     appWidgetInfo.cellX = c.getInt(cellXIndex);                          
2282                                     appWidgetInfo.cellY = c.getInt(cellYIndex);                          
2283                                     appWidgetInfo.spanX = c.getInt(spanXIndex);                          
2284                                     appWidgetInfo.spanY = c.getInt(spanYIndex);                          
2285                                                                                                          
2286                                     container = c.getInt(containerIndex);                                
2287                                     if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&     
2288                                         container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {     
2289                                         Log.e(TAG, "Widget found where container != " +                  
2290                                             "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");      
2291                                         continue;                                                        
2292                                     }                                                                    
2293                                                                                                          
2294                                     appWidgetInfo.container = c.getInt(containerIndex);                  
2295                                     // check & update map of what's occupied                             
2296                                     deleteOnInvalidPlacement.set(false);                                 
2297                                     if (!checkItemPlacement(occupied, appWidgetInfo,                     
2298                                             deleteOnInvalidPlacement)) {                                 
2299                                         if (deleteOnInvalidPlacement.get()) {                            
2300                                             itemsToRemove.add(id);                                       
2301                                         }                                                                
2302                                         break;                                                           
2303                                     }                                                                    
2304                                                                                                          
2305                                     String providerName = appWidgetInfo.providerName.flattenToString();  
2306                                     if (!providerName.equals(savedProvider) ||                           
2307                                             (appWidgetInfo.restoreStatus != restoreStatus)) {            
2308                                         ContentValues values = new ContentValues();                      
2309                                         values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,        
2310                                                 providerName);                                           
2311                                         values.put(LauncherSettings.Favorites.RESTORED,                  
2312                                                 appWidgetInfo.restoreStatus);                            
2313                                         String where = BaseColumns._ID + "= ?";                          
2314                                         String[] args = {Long.toString(id)};                             
2315                                         contentResolver.update(contentUri, values, where, args);         
2316                                     }                                                                    
2317                                     sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);                  
2318                                     sBgAppWidgets.add(appWidgetInfo);                                    
2319                                 }                                                                        
2320                                 break;                                                                   
2321                             }                                                                            
2322                         } catch (Exception e) {                                                          
2323                             Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);      
2324                         }                                                                                
2325                     }                                                                                    
2326                 } finally {                                                                              
2327                     if (c != null) {                                                                     
2328                         c.close();                                                                       
2329                     }                                                                                    
2330                 }                                                                                        
2331                                                                                                          
2332                 // Break early if we've stopped loading                                                  
2333                 if (mStopped) {                                                                          
2334                     clearSBgDataStructures();                                                            
2335                     return false;                                                                        
2336                 }                                                                                        
2337                                                                                                          
2338                 if (itemsToRemove.size() > 0) {                                                          
2339                     ContentProviderClient client = contentResolver.acquireContentProviderClient(         
2340                             contentUri);                                                                 
2341                     // Remove dead items                                                                 
2342                     for (long id : itemsToRemove) {                                                      
2343                         if (DEBUG_LOADERS) {                                                             
2344                             Log.d(TAG, "Removed id = " + id);                                            
2345                         }                                                                                
2346                         // Don't notify content observers                                                
2347                         try {                                                                            
2348                             client.delete(LauncherSettings.Favorites.getContentUri(id, false),           
2349                                     null, null);                                                         
2350                         } catch (RemoteException e) {                                                    
2351                             Log.w(TAG, "Could not remove id = " + id);                                   
2352                         }                                                                                
2353                     }                                                                                    
2354                 }                                                                                        
2355                                                                                                          
2356                 if (restoredRows.size() > 0) {                                                           
2357                     ContentProviderClient updater = contentResolver.acquireContentProviderClient(        
2358                             contentUri);                                                                 
2359                     // Update restored items that no longer require special handling                     
2360                     try {                                                                                
2361                         StringBuilder selectionBuilder = new StringBuilder();                            
2362                         selectionBuilder.append(LauncherSettings.Favorites._ID);                         
2363                         selectionBuilder.append(" IN (");                                                
2364                         selectionBuilder.append(TextUtils.join(", ", restoredRows));                     
2365                         selectionBuilder.append(")");                                                    
2366                         ContentValues values = new ContentValues();                                      
2367                         values.put(LauncherSettings.Favorites.RESTORED, 0);                              
2368                         updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,           
2369                                 values, selectionBuilder.toString(), null);                              
2370                     } catch (RemoteException e) {                                                        
2371                         Log.w(TAG, "Could not update restored rows");                                    
2372                     }                                                                                    
2373                 }                                                                                        
2374                                                                                                          
2375                 if (!isSdCardReady && !sPendingPackages.isEmpty()) {                                     
2376                     context.registerReceiver(new AppsAvailabilityCheck(),                                
2377                             new IntentFilter(StartupReceiver.SYSTEM_READY),                              
2378                             null, sWorker);                                                              
2379                 }                                                                                        
2380                                                                                                          
2381                 if (loadedOldDb) {                                                                       
2382                     long maxScreenId = 0;                                                                
2383                     // If we're importing we use the old screen order.                                   
2384                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
2385                         long screenId = item.screenId;                                                   
2386                         if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&            
2387                                 !sBgWorkspaceScreens.contains(screenId)) {                               
2388                             sBgWorkspaceScreens.add(screenId);                                           
2389                             if (screenId > maxScreenId) {                                                
2390                                 maxScreenId = screenId;                                                  
2391                             }                                                                            
2392                         }                                                                                
2393                     }                                                                                    
2394                     Collections.sort(sBgWorkspaceScreens);                                               
2395                     // Log to disk                                                                       
2396                     Launcher.addDumpLog(TAG, "11683562 -   maxScreenId: " + maxScreenId, true);          
2397                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                      
2398                             TextUtils.join(", ", sBgWorkspaceScreens), true);                            
2399                                                                                                          
2400                     LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);               
2401                     updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                            
2402                                                                                                          
2403                     // Update the max item id after we load an old db                                    
2404                     long maxItemId = 0;                                                                  
2405                     // If we're importing we use the old screen order.                                   
2406                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
2407                         maxItemId = Math.max(maxItemId, item.id);                                        
2408                     }                                                                                    
2409                     LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);                   
2410                 } else {                                                                                 
2411                     TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(mContext);            
2412                     for (Integer i : orderedScreens.keySet()) {                                          
2413                         sBgWorkspaceScreens.add(orderedScreens.get(i));                                  
2414                     }                                                                                    
2415                     // Log to disk                                                                       
2416                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                      
2417                             TextUtils.join(", ", sBgWorkspaceScreens), true);                            
2418                                                                                                          
2419                     // Remove any empty screens                                                          
2420                     ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);            
2421                     for (ItemInfo item: sBgItemsIdMap.values()) {                                        
2422                         long screenId = item.screenId;                                                   
2423                         if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&            
2424                                 unusedScreens.contains(screenId)) {                                      
2425                             unusedScreens.remove(screenId);                                              
2426                         }                                                                                
2427                     }                                                                                    
2428                                                                                                          
2429                     // If there are any empty screens remove them, and update.                           
2430                     if (unusedScreens.size() != 0) {                                                     
2431                         // Log to disk                                                                   
2432                         Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " +        
2433                                 TextUtils.join(", ", unusedScreens), true);                              
2434                                                                                                          
2435                         sBgWorkspaceScreens.removeAll(unusedScreens);                                    
2436                         updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                        
2437                     }                                                                                    
2438                 }                                                                                        
2439                                                                                                          
2440                 if (DEBUG_LOADERS) {                                                                     
2441                     Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");          
2442                     Log.d(TAG, "workspace layout: ");                                                    
2443                     int nScreens = occupied.size();                                                      
2444                     for (int y = 0; y < countY; y++) {                                                   
2445                         String line = "";                                                                
2446                                                                                                          
2447                         Iterator<Long> iter = occupied.keySet().iterator();                              
2448                         while (iter.hasNext()) {                                                         
2449                             long screenId = iter.next();                                                 
2450                             if (screenId > 0) {                                                          
2451                                 line += " | ";                                                           
2452                             }                                                                            
2453                             for (int x = 0; x < countX; x++) {                                           
2454                                 ItemInfo[][] screen = occupied.get(screenId);                            
2455                                 if (x < screen.length && y < screen[x].length) {                         
2456                                     line += (screen[x][y] != null) ? "#" : ".";                          
2457                                 } else {                                                                 
2458                                     line += "!";                                                         
2459                                 }                                                                        
2460                             }                                                                            
2461                         }                                                                                
2462                         Log.d(TAG, "[ " + line + " ]");                                                  
2463                     }                                                                                    
2464                 }                                                                                        
2465             }                                                                                            
2466             return loadedOldDb;                                                                          
2467         }                                                                                                
2468                                                                                                          
2469         /** Filters the set of items who are directly or indirectly (via another container) on the       
2470          * specified screen. */                                                                          
2471         private void filterCurrentWorkspaceItems(long currentScreenId,                                   
2472                 ArrayList<ItemInfo> allWorkspaceItems,                                                   
2473                 ArrayList<ItemInfo> currentScreenItems,                                                  
2474                 ArrayList<ItemInfo> otherScreenItems) {                                                  
2475             // Purge any null ItemInfos                                                                  
2476             Iterator<ItemInfo> iter = allWorkspaceItems.iterator();                                      
2477             while (iter.hasNext()) {                                                                     
2478                 ItemInfo i = iter.next();                                                                
2479                 if (i == null) {                                                                         
2480                     iter.remove();                                                                       
2481                 }                                                                                        
2482             }                                                                                            
2483                                                                                                          
2484             // Order the set of items by their containers first, this allows use to walk through the     
2485             // list sequentially, build up a list of containers that are in the specified screen,        
2486             // as well as all items in those containers.                                                 
2487             Set<Long> itemsOnScreen = new HashSet<Long>();                                               
2488             Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {                             
2489                 @Override                                                                                
2490                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
2491                     return (int) (lhs.container - rhs.container);                                        
2492                 }                                                                                        
2493             });                                                                                          
2494             for (ItemInfo info : allWorkspaceItems) {                                                    
2495                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                    
2496                     if (info.screenId == currentScreenId) {                                              
2497                         currentScreenItems.add(info);                                                    
2498                         itemsOnScreen.add(info.id);                                                      
2499                     } else {                                                                             
2500                         otherScreenItems.add(info);                                                      
2501                     }                                                                                    
2502                 } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {             
2503                     currentScreenItems.add(info);                                                        
2504                     itemsOnScreen.add(info.id);                                                          
2505                 } else {                                                                                 
2506                     if (itemsOnScreen.contains(info.container)) {                                        
2507                         currentScreenItems.add(info);                                                    
2508                         itemsOnScreen.add(info.id);                                                      
2509                     } else {                                                                             
2510                         otherScreenItems.add(info);                                                      
2511                     }                                                                                    
2512                 }                                                                                        
2513             }                                                                                            
2514         }                                                                                                
2515                                                                                                          
2516         /** Filters the set of widgets which are on the specified screen. */                             
2517         private void filterCurrentAppWidgets(long currentScreenId,                                       
2518                 ArrayList<LauncherAppWidgetInfo> appWidgets,                                             
2519                 ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,                                   
2520                 ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {                                   
2521                                                                                                          
2522             for (LauncherAppWidgetInfo widget : appWidgets) {                                            
2523                 if (widget == null) continue;                                                            
2524                 if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                  
2525                         widget.screenId == currentScreenId) {                                            
2526                     currentScreenWidgets.add(widget);                                                    
2527                 } else {                                                                                 
2528                     otherScreenWidgets.add(widget);                                                      
2529                 }                                                                                        
2530             }                                                                                            
2531         }                                                                                                
2532                                                                                                          
2533         /** Filters the set of folders which are on the specified screen. */                             
2534         private void filterCurrentFolders(long currentScreenId,                                          
2535                 HashMap<Long, ItemInfo> itemsIdMap,                                                      
2536                 HashMap<Long, FolderInfo> folders,                                                       
2537                 HashMap<Long, FolderInfo> currentScreenFolders,                                          
2538                 HashMap<Long, FolderInfo> otherScreenFolders) {                                          
2539                                                                                                          
2540             for (long id : folders.keySet()) {                                                           
2541                 ItemInfo info = itemsIdMap.get(id);                                                      
2542                 FolderInfo folder = folders.get(id);                                                     
2543                 if (info == null || folder == null) continue;                                            
2544                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                    
2545                         info.screenId == currentScreenId) {                                              
2546                     currentScreenFolders.put(id, folder);                                                
2547                 } else {                                                                                 
2548                     otherScreenFolders.put(id, folder);                                                  
2549                 }                                                                                        
2550             }                                                                                            
2551         }                                                                                                
2552                                                                                                          
2553         /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to          
2554          * right) */                                                                                     
2555         private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {                   
2556             final LauncherAppState app = LauncherAppState.getInstance();                                 
2557             final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                          
2558             // XXX: review this                                                                          
2559             Collections.sort(workspaceItems, new Comparator<ItemInfo>() {                                
2560                 @Override                                                                                
2561                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
2562                     int cellCountX = (int) grid.numColumns;                                              
2563                     int cellCountY = (int) grid.numRows;                                                 
2564                     int screenOffset = cellCountX * cellCountY;                                          
2565                     int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat      
2566                     long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +           
2567                             lhs.cellY * cellCountX + lhs.cellX);                                         
2568                     long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +           
2569                             rhs.cellY * cellCountX + rhs.cellX);                                         
2570                     return (int) (lr - rr);                                                              
2571                 }                                                                                        
2572             });                                                                                          
2573         }                                                                                                
2574                                                                                                          
2575         private void bindWorkspaceScreens(final Callbacks oldCallbacks,                                  
2576                 final ArrayList<Long> orderedScreens) {                                                  
2577             final Runnable r = new Runnable() {                                                          
2578                 @Override                                                                                
2579                 public void run() {                                                                      
2580                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2581                     if (callbacks != null) {                                                             
2582                         callbacks.bindScreens(orderedScreens);                                           
2583                     }                                                                                    
2584                 }                                                                                        
2585             };                                                                                           
2586             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
2587         }                                                                                                
2588                                                                                                          
2589         private void bindWorkspaceItems(final Callbacks oldCallbacks,                                    
2590                 final ArrayList<ItemInfo> workspaceItems,                                                
2591                 final ArrayList<LauncherAppWidgetInfo> appWidgets,                                       
2592                 final HashMap<Long, FolderInfo> folders,                                                 
2593                 ArrayList<Runnable> deferredBindRunnables) {                                             
2594                                                                                                          
2595             final boolean postOnMainThread = (deferredBindRunnables != null);                            
2596                                                                                                          
2597             // Bind the workspace items                                                                  
2598             int N = workspaceItems.size();                                                               
2599             for (int i = 0; i < N; i += ITEMS_CHUNK) {                                                   
2600                 final int start = i;                                                                     
2601                 final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);                        
2602                 final Runnable r = new Runnable() {                                                      
2603                     @Override                                                                            
2604                     public void run() {                                                                  
2605                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2606                         if (callbacks != null) {                                                         
2607                             callbacks.bindItems(workspaceItems, start, start+chunkSize,                  
2608                                     false);                                                              
2609                         }                                                                                
2610                     }                                                                                    
2611                 };                                                                                       
2612                 if (postOnMainThread) {                                                                  
2613                     synchronized (deferredBindRunnables) {                                               
2614                         deferredBindRunnables.add(r);                                                    
2615                     }                                                                                    
2616                 } else {                                                                                 
2617                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2618                 }                                                                                        
2619             }                                                                                            
2620                                                                                                          
2621             // Bind the folders                                                                          
2622             if (!folders.isEmpty()) {                                                                    
2623                 final Runnable r = new Runnable() {                                                      
2624                     public void run() {                                                                  
2625                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2626                         if (callbacks != null) {                                                         
2627                             callbacks.bindFolders(folders);                                              
2628                         }                                                                                
2629                     }                                                                                    
2630                 };                                                                                       
2631                 if (postOnMainThread) {                                                                  
2632                     synchronized (deferredBindRunnables) {                                               
2633                         deferredBindRunnables.add(r);                                                    
2634                     }                                                                                    
2635                 } else {                                                                                 
2636                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2637                 }                                                                                        
2638             }                                                                                            
2639                                                                                                          
2640             // Bind the widgets, one at a time                                                           
2641             N = appWidgets.size();                                                                       
2642             for (int i = 0; i < N; i++) {                                                                
2643                 final LauncherAppWidgetInfo widget = appWidgets.get(i);                                  
2644                 final Runnable r = new Runnable() {                                                      
2645                     public void run() {                                                                  
2646                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2647                         if (callbacks != null) {                                                         
2648                             callbacks.bindAppWidget(widget);                                             
2649                         }                                                                                
2650                     }                                                                                    
2651                 };                                                                                       
2652                 if (postOnMainThread) {                                                                  
2653                     deferredBindRunnables.add(r);                                                        
2654                 } else {                                                                                 
2655                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2656                 }                                                                                        
2657             }                                                                                            
2658         }                                                                                                
2659                                                                                                          
2660         /**                                                                                              
2661          * Binds all loaded data to actual views on the main thread.                                     
2662          */                                                                                              
2663         private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {               
2664             final long t = SystemClock.uptimeMillis();                                                   
2665             Runnable r;                                                                                  
2666                                                                                                          
2667             // Don't use these two variables in any of the callback runnables.                           
2668             // Otherwise we hold a reference to them.                                                    
2669             final Callbacks oldCallbacks = mCallbacks.get();                                             
2670             if (oldCallbacks == null) {                                                                  
2671                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2672                 Log.w(TAG, "LoaderTask running with no launcher");                                       
2673                 return;                                                                                  
2674             }                                                                                            
2675                                                                                                          
2676             // Save a copy of all the bg-thread collections                                              
2677             ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();                              
2678             ArrayList<LauncherAppWidgetInfo> appWidgets =                                                
2679                     new ArrayList<LauncherAppWidgetInfo>();                                              
2680             HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();                         
2681             HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();                          
2682             ArrayList<Long> orderedScreenIds = new ArrayList<Long>();                                    
2683             synchronized (sBgLock) {                                                                     
2684                 workspaceItems.addAll(sBgWorkspaceItems);                                                
2685                 appWidgets.addAll(sBgAppWidgets);                                                        
2686                 folders.putAll(sBgFolders);                                                              
2687                 itemsIdMap.putAll(sBgItemsIdMap);                                                        
2688                 orderedScreenIds.addAll(sBgWorkspaceScreens);                                            
2689             }                                                                                            
2690                                                                                                          
2691             final boolean isLoadingSynchronously =                                                       
2692                     synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;                               
2693             int currScreen = isLoadingSynchronously ? synchronizeBindPage :                              
2694                 oldCallbacks.getCurrentWorkspaceScreen();                                                
2695             if (currScreen >= orderedScreenIds.size()) {                                                 
2696                 // There may be no workspace screens (just hotseat items and an empty page).             
2697                 currScreen = PagedView.INVALID_RESTORE_PAGE;                                             
2698             }                                                                                            
2699             final int currentScreen = currScreen;                                                        
2700             final long currentScreenId = currentScreen < 0                                               
2701                     ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);                           
2702                                                                                                          
2703             // Load all the items that are on the current page first (and in the process, unbind         
2704             // all the existing workspace items before we call startBinding() below.                     
2705             unbindWorkspaceItemsOnMainThread();                                                          
2706                                                                                                          
2707             // Separate the items that are on the current screen, and all the other remaining items      
2708             ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();                       
2709             ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();                         
2710             ArrayList<LauncherAppWidgetInfo> currentAppWidgets =                                         
2711                     new ArrayList<LauncherAppWidgetInfo>();                                              
2712             ArrayList<LauncherAppWidgetInfo> otherAppWidgets =                                           
2713                     new ArrayList<LauncherAppWidgetInfo>();                                              
2714             HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();                  
2715             HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();                    
2716                                                                                                          
2717             filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,          
2718                     otherWorkspaceItems);                                                                
2719             filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,                      
2720                     otherAppWidgets);                                                                    
2721             filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,                   
2722                     otherFolders);                                                                       
2723             sortWorkspaceItemsSpatially(currentWorkspaceItems);                                          
2724             sortWorkspaceItemsSpatially(otherWorkspaceItems);                                            
2725                                                                                                          
2726             // Tell the workspace that we're about to start binding items                                
2727             r = new Runnable() {                                                                         
2728                 public void run() {                                                                      
2729                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2730                     if (callbacks != null) {                                                             
2731                         callbacks.startBinding();                                                        
2732                     }                                                                                    
2733                 }                                                                                        
2734             };                                                                                           
2735             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
2736                                                                                                          
2737             bindWorkspaceScreens(oldCallbacks, orderedScreenIds);                                        
2738                                                                                                          
2739             // Load items on the current page                                                            
2740             bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,                   
2741                     currentFolders, null);                                                               
2742             if (isLoadingSynchronously) {                                                                
2743                 r = new Runnable() {                                                                     
2744                     public void run() {                                                                  
2745                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2746                         if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {      
2747                             callbacks.onPageBoundSynchronously(currentScreen);                           
2748                         }                                                                                
2749                     }                                                                                    
2750                 };                                                                                       
2751                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
2752             }                                                                                            
2753                                                                                                          
2754             // Load all the remaining pages (if we are loading synchronously, we want to defer this      
2755             // work until after the first render)                                                        
2756             synchronized (mDeferredBindRunnables) {                                                      
2757                 mDeferredBindRunnables.clear();                                                          
2758             }                                                                                            
2759             bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,         
2760                     (isLoadingSynchronously ? mDeferredBindRunnables : null));                           
2761                                                                                                          
2762             // Tell the workspace that we're done binding items                                          
2763             r = new Runnable() {                                                                         
2764                 public void run() {                                                                      
2765                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2766                     if (callbacks != null) {                                                             
2767                         callbacks.finishBindingItems(isUpgradePath);                                     
2768                     }                                                                                    
2769                                                                                                          
2770                     // If we're profiling, ensure this is the last thing in the queue.                   
2771                     if (DEBUG_LOADERS) {                                                                 
2772                         Log.d(TAG, "bound workspace in "                                                 
2773                             + (SystemClock.uptimeMillis()-t) + "ms");                                    
2774                     }                                                                                    
2775                                                                                                          
2776                     mIsLoadingAndBindingWorkspace = false;                                               
2777                 }                                                                                        
2778             };                                                                                           
2779             if (isLoadingSynchronously) {                                                                
2780                 synchronized (mDeferredBindRunnables) {                                                  
2781                     mDeferredBindRunnables.add(r);                                                       
2782                 }                                                                                        
2783             } else {                                                                                     
2784                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
2785             }                                                                                            
2786         }                                                                                                
2787                                                                                                          
2788         private void loadAndBindAllApps() {                                                              
2789             if (DEBUG_LOADERS) {                                                                         
2790                 Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);                       
2791             }                                                                                            
2792             if (!mAllAppsLoaded) {                                                                       
2793                 loadAllApps();                                                                           
2794                 synchronized (LoaderTask.this) {                                                         
2795                     if (mStopped) {                                                                      
2796                         return;                                                                          
2797                     }                                                                                    
2798                     mAllAppsLoaded = true;                                                               
2799                 }                                                                                        
2800             } else {                                                                                     
2801                 onlyBindAllApps();                                                                       
2802             }                                                                                            
2803         }                                                                                                
2804                                                                                                          
2805         private void onlyBindAllApps() {                                                                 
2806             final Callbacks oldCallbacks = mCallbacks.get();                                             
2807             if (oldCallbacks == null) {                                                                  
2808                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2809                 Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");                     
2810                 return;                                                                                  
2811             }                                                                                            
2812                                                                                                          
2813             // shallow copy                                                                              
2814             @SuppressWarnings("unchecked")                                                               
2815             final ArrayList<AppInfo> list                                                                
2816                     = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();                                  
2817             Runnable r = new Runnable() {                                                                
2818                 public void run() {                                                                      
2819                     final long t = SystemClock.uptimeMillis();                                           
2820                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
2821                     if (callbacks != null) {                                                             
2822                         callbacks.bindAllApplications(list);                                             
2823                     }                                                                                    
2824                     if (DEBUG_LOADERS) {                                                                 
2825                         Log.d(TAG, "bound all " + list.size() + " apps from cache in "                   
2826                                 + (SystemClock.uptimeMillis()-t) + "ms");                                
2827                     }                                                                                    
2828                 }                                                                                        
2829             };                                                                                           
2830             boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());           
2831             if (isRunningOnMainThread) {                                                                 
2832                 r.run();                                                                                 
2833             } else {                                                                                     
2834                 mHandler.post(r);                                                                        
2835             }                                                                                            
2836         }                                                                                                
2837                                                                                                          
2838         private void loadAllApps() {                                                                     
2839             final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                        
2840                                                                                                          
2841             final Callbacks oldCallbacks = mCallbacks.get();                                             
2842             if (oldCallbacks == null) {                                                                  
2843                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2844                 Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");                         
2845                 return;                                                                                  
2846             }                                                                                            
2847                                                                                                          
2848             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);                              
2849             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                            
2850                                                                                                          
2851             final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();                      
2852                                                                                                          
2853             // Clear the list of apps                                                                    
2854             mBgAllAppsList.clear();                                                                      
2855             for (UserHandleCompat user : profiles) {                                                     
2856                 // Query for the set of apps                                                             
2857                 final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                     
2858                 List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);       
2859                 if (DEBUG_LOADERS) {                                                                     
2860                     Log.d(TAG, "getActivityList took "                                                   
2861                             + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);             
2862                     Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);         
2863                 }                                                                                        
2864                 // Fail if we don't have any apps                                                        
2865                 if (apps == null || apps.isEmpty()) {                                                    
2866                     return;                                                                              
2867                 }                                                                                        
2868                 // Sort the applications by name                                                         
2869                 final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                    
2870                 Collections.sort(apps,                                                                   
2871                         new LauncherModel.ShortcutNameComparator(mLabelCache));                          
2872                 if (DEBUG_LOADERS) {                                                                     
2873                     Log.d(TAG, "sort took "                                                              
2874                             + (SystemClock.uptimeMillis()-sortTime) + "ms");                             
2875                 }                                                                                        
2876                                                                                                          
2877                 // Create the ApplicationInfos                                                           
2878                 for (int i = 0; i < apps.size(); i++) {                                                  
2879                     LauncherActivityInfoCompat app = apps.get(i);                                        
2880                     // This builds the icon bitmaps.                                                     
2881                     mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));       
2882                 }                                                                                        
2883             }                                                                                            
2884             // Huh? Shouldn't this be inside the Runnable below?                                         
2885             final ArrayList<AppInfo> added = mBgAllAppsList.added;                                       
2886             mBgAllAppsList.added = new ArrayList<AppInfo>();                                             
2887                                                                                                          
2888             // Post callback on main thread                                                              
2889             mHandler.post(new Runnable() {                                                               
2890                 public void run() {                                                                      
2891                     final long bindTime = SystemClock.uptimeMillis();                                    
2892                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
2893                     if (callbacks != null) {                                                             
2894                         callbacks.bindAllApplications(added);                                            
2895                         if (DEBUG_LOADERS) {                                                             
2896                             Log.d(TAG, "bound " + added.size() + " apps in "                             
2897                                 + (SystemClock.uptimeMillis() - bindTime) + "ms");                       
2898                         }                                                                                
2899                     } else {                                                                             
2900                         Log.i(TAG, "not binding apps: no Launcher activity");                            
2901                     }                                                                                    
2902                 }                                                                                        
2903             });                                                                                          
2904                                                                                                          
2905             if (DEBUG_LOADERS) {                                                                         
2906                 Log.d(TAG, "Icons processed in "                                                         
2907                         + (SystemClock.uptimeMillis() - loadTime) + "ms");                               
2908             }                                                                                            
2909         }                                                                                                
2910                                                                                                          
2911         public void dumpState() {                                                                        
2912             synchronized (sBgLock) {                                                                     
2913                 Log.d(TAG, "mLoaderTask.mContext=" + mContext);                                          
2914                 Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);                                  
2915                 Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);                                          
2916                 Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);          
2917                 Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());                                   
2918             }                                                                                            
2919         }                                                                                                
2920     }                                                                                                    
2921                                                                                                          
2922     void enqueuePackageUpdated(PackageUpdatedTask task) {                                                
2923         sWorker.post(task);                                                                              
2924     }                                                                                                    
2925                                                                                                          
2926     private class AppsAvailabilityCheck extends BroadcastReceiver {                                      
2927                                                                                                          
2928         @Override                                                                                        
2929         public void onReceive(Context context, Intent intent) {                                          
2930             synchronized (sBgLock) {                                                                     
2931                 final LauncherAppsCompat launcherApps = LauncherAppsCompat                               
2932                         .getInstance(mApp.getContext());                                                 
2933                 ArrayList<String> packagesRemoved;                                                       
2934                 for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {     
2935                     UserHandleCompat user = entry.getKey();                                              
2936                     packagesRemoved = new ArrayList<String>();                                           
2937                     for (String pkg : entry.getValue()) {                                                
2938                         if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {                       
2939                             Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);                 
2940                             packagesRemoved.add(pkg);                                                    
2941                         }                                                                                
2942                     }                                                                                    
2943                     if (!packagesRemoved.isEmpty()) {                                                    
2944                         enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,       
2945                                 packagesRemoved.toArray(new String[packagesRemoved.size()]), user));     
2946                     }                                                                                    
2947                 }                                                                                        
2948                 sPendingPackages.clear();                                                                
2949             }                                                                                            
2950         }                                                                                                
2951     }                                                                                                    
2952                                                                                                          
2953     /**                                                                                                  
2954      * Workaround to re-check unrestored items, in-case they were installed but the Package-ADD          
2955      * runnable was missed by the launcher.                                                              
2956      */                                                                                                  
2957     public void recheckRestoredItems(final Context context) {                                            
2958         Runnable r = new Runnable() {                                                                    
2959                                                                                                          
2960             @Override                                                                                    
2961             public void run() {                                                                          
2962                 LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);               
2963                 HashSet<String> installedPackages = new HashSet<String>();                               
2964                 UserHandleCompat user = UserHandleCompat.myUserHandle();                                 
2965                 synchronized(sBgLock) {                                                                  
2966                     for (ItemInfo info : sBgItemsIdMap.values()) {                                       
2967                         if (info instanceof ShortcutInfo) {                                              
2968                             ShortcutInfo si = (ShortcutInfo) info;                                       
2969                             if (si.isPromise() && si.getTargetComponent() != null                        
2970                                     && launcherApps.isPackageEnabledForProfile(                          
2971                                             si.getTargetComponent().getPackageName(), user)) {           
2972                                 installedPackages.add(si.getTargetComponent().getPackageName());         
2973                             }                                                                            
2974                         } else if (info instanceof LauncherAppWidgetInfo) {                              
2975                             LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) info;                 
2976                             if (widget.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)     
2977                                     && launcherApps.isPackageEnabledForProfile(                          
2978                                             widget.providerName.getPackageName(), user)) {               
2979                                 installedPackages.add(widget.providerName.getPackageName());             
2980                             }                                                                            
2981                         }                                                                                
2982                     }                                                                                    
2983                 }                                                                                        
2984                                                                                                          
2985                 if (!installedPackages.isEmpty()) {                                                      
2986                     final ArrayList<AppInfo> restoredApps = new ArrayList<AppInfo>();                    
2987                     for (String pkg : installedPackages) {                                               
2988                         for (LauncherActivityInfoCompat info : launcherApps.getActivityList(pkg, user)) {
2989                             restoredApps.add(new AppInfo(context, info, user, mIconCache, null));        
2990                         }                                                                                
2991                     }                                                                                    
2992                                                                                                          
2993                     final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;            
2994                     if (!restoredApps.isEmpty()) {                                                       
2995                         mHandler.post(new Runnable() {                                                   
2996                             public void run() {                                                          
2997                                 Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;             
2998                                 if (callbacks == cb && cb != null) {                                     
2999                                     callbacks.bindAppsRestored(restoredApps);                            
3000                                 }                                                                        
3001                             }                                                                            
3002                         });                                                                              
3003                     }                                                                                    
3004                                                                                                          
3005                 }                                                                                        
3006             }                                                                                            
3007         };                                                                                               
3008         sWorker.post(r);                                                                                 
3009     }                                                                                                    
3010                                                                                                          
3011     private class PackageUpdatedTask implements Runnable {                                               
3012         int mOp;                                                                                         
3013         String[] mPackages;                                                                              
3014         UserHandleCompat mUser;                                                                          
3015                                                                                                          
3016         public static final int OP_NONE = 0;                                                             
3017         public static final int OP_ADD = 1;                                                              
3018         public static final int OP_UPDATE = 2;                                                           
3019         public static final int OP_REMOVE = 3; // uninstlled                                             
3020         public static final int OP_UNAVAILABLE = 4; // external media unmounted                          
3021                                                                                                          
3022                                                                                                          
3023         public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {                    
3024             mOp = op;                                                                                    
3025             mPackages = packages;                                                                        
3026             mUser = user;                                                                                
3027         }                                                                                                
3028                                                                                                          
3029         public void run() {                                                                              
3030             final Context context = mApp.getContext();                                                   
3031                                                                                                          
3032             final String[] packages = mPackages;                                                         
3033             final int N = packages.length;                                                               
3034             switch (mOp) {                                                                               
3035                 case OP_ADD:                                                                             
3036                     for (int i=0; i<N; i++) {                                                            
3037                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);         
3038                         mIconCache.remove(packages[i], mUser);                                           
3039                         mBgAllAppsList.addPackage(context, packages[i], mUser);                          
3040                     }                                                                                    
3041                     break;                                                                               
3042                 case OP_UPDATE:                                                                          
3043                     for (int i=0; i<N; i++) {                                                            
3044                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);      
3045                         mBgAllAppsList.updatePackage(context, packages[i], mUser);                       
3046                         WidgetPreviewLoader.removePackageFromDb(                                         
3047                                 mApp.getWidgetPreviewCacheDb(), packages[i]);                            
3048                     }                                                                                    
3049                     break;                                                                               
3050                 case OP_REMOVE:                                                                          
3051                 case OP_UNAVAILABLE:                                                                     
3052                     for (int i=0; i<N; i++) {                                                            
3053                         if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);      
3054                         mBgAllAppsList.removePackage(packages[i], mUser);                                
3055                         WidgetPreviewLoader.removePackageFromDb(                                         
3056                                 mApp.getWidgetPreviewCacheDb(), packages[i]);                            
3057                     }                                                                                    
3058                     break;                                                                               
3059             }                                                                                            
3060                                                                                                          
3061             ArrayList<AppInfo> added = null;                                                             
3062             ArrayList<AppInfo> modified = null;                                                          
3063             final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();                             
3064                                                                                                          
3065             if (mBgAllAppsList.added.size() > 0) {                                                       
3066                 added = new ArrayList<AppInfo>(mBgAllAppsList.added);                                    
3067                 mBgAllAppsList.added.clear();                                                            
3068             }                                                                                            
3069             if (mBgAllAppsList.modified.size() > 0) {                                                    
3070                 modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);                              
3071                 mBgAllAppsList.modified.clear();                                                         
3072             }                                                                                            
3073             if (mBgAllAppsList.removed.size() > 0) {                                                     
3074                 removedApps.addAll(mBgAllAppsList.removed);                                              
3075                 mBgAllAppsList.removed.clear();                                                          
3076             }                                                                                            
3077                                                                                                          
3078             final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                    
3079             if (callbacks == null) {                                                                     
3080                 Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");          
3081                 return;                                                                                  
3082             }                                                                                            
3083                                                                                                          
3084             if (added != null) {                                                                         
3085                 // Ensure that we add all the workspace applications to the db                           
3086                 if (LauncherAppState.isDisableAllApps()) {                                               
3087                     final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);               
3088                     addAndBindAddedWorkspaceApps(context, addedInfos);                                   
3089                 } else {                                                                                 
3090                     addAppsToAllApps(context, added);                                                    
3091                 }                                                                                        
3092             }                                                                                            
3093                                                                                                          
3094             if (modified != null) {                                                                      
3095                 final ArrayList<AppInfo> modifiedFinal = modified;                                       
3096                                                                                                          
3097                 // Update the launcher db to reflect the changes                                         
3098                 for (AppInfo a : modifiedFinal) {                                                        
3099                     ArrayList<ItemInfo> infos =                                                          
3100                             getItemInfoForComponentName(a.componentName, mUser);                         
3101                     for (ItemInfo i : infos) {                                                           
3102                         if (isShortcutInfoUpdateable(i)) {                                               
3103                             ShortcutInfo info = (ShortcutInfo) i;                                        
3104                             info.title = a.title.toString();                                             
3105                             info.contentDescription = a.contentDescription;                              
3106                             updateItemInDatabase(context, info);                                         
3107                         }                                                                                
3108                     }                                                                                    
3109                 }                                                                                        
3110                                                                                                          
3111                 mHandler.post(new Runnable() {                                                           
3112                     public void run() {                                                                  
3113                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
3114                         if (callbacks == cb && cb != null) {                                             
3115                             callbacks.bindAppsUpdated(modifiedFinal);                                    
3116                         }                                                                                
3117                     }                                                                                    
3118                 });                                                                                      
3119             }                                                                                            
3120                                                                                                          
3121             final ArrayList<String> removedPackageNames =                                                
3122                     new ArrayList<String>();                                                             
3123             if (mOp == OP_REMOVE) {                                                                      
3124                 // Mark all packages in the broadcast to be removed                                      
3125                 removedPackageNames.addAll(Arrays.asList(packages));                                     
3126             } else if (mOp == OP_UPDATE) {                                                               
3127                 // Mark disabled packages in the broadcast to be removed                                 
3128                 final PackageManager pm = context.getPackageManager();                                   
3129                 for (int i=0; i<N; i++) {                                                                
3130                     if (isPackageDisabled(context, packages[i], mUser)) {                                
3131                         removedPackageNames.add(packages[i]);                                            
3132                     }                                                                                    
3133                 }                                                                                        
3134             }                                                                                            
3135             // Remove all the components associated with this package                                    
3136             for (String pn : removedPackageNames) {                                                      
3137                 deletePackageFromDatabase(context, pn, mUser);                                           
3138             }                                                                                            
3139             // Remove all the specific components                                                        
3140             for (AppInfo a : removedApps) {                                                              
3141                 ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);         
3142                 deleteItemsFromDatabase(context, infos);                                                 
3143             }                                                                                            
3144             if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {                              
3145                 // Remove any queued items from the install queue                                        
3146                 String spKey = LauncherAppState.getSharedPreferencesKey();                               
3147                 SharedPreferences sp =                                                                   
3148                         context.getSharedPreferences(spKey, Context.MODE_PRIVATE);                       
3149                 InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);                 
3150                 // Call the components-removed callback                                                  
3151                 mHandler.post(new Runnable() {                                                           
3152                     public void run() {                                                                  
3153                         Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                     
3154                         if (callbacks == cb && cb != null) {                                             
3155                             callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);    
3156                         }                                                                                
3157                     }                                                                                    
3158                 });                                                                                      
3159             }                                                                                            
3160                                                                                                          
3161             final ArrayList<Object> widgetsAndShortcuts =                                                
3162                     getSortedWidgetsAndShortcuts(context);                                               
3163             mHandler.post(new Runnable() {                                                               
3164                 @Override                                                                                
3165                 public void run() {                                                                      
3166                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
3167                     if (callbacks == cb && cb != null) {                                                 
3168                         callbacks.bindPackagesUpdated(widgetsAndShortcuts);                              
3169                     }                                                                                    
3170                 }                                                                                        
3171             });                                                                                          
3172                                                                                                          
3173             // Write all the logs to disk                                                                
3174             mHandler.post(new Runnable() {                                                               
3175                 public void run() {                                                                      
3176                     Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                         
3177                     if (callbacks == cb && cb != null) {                                                 
3178                         callbacks.dumpLogsToLocalData();                                                 
3179                     }                                                                                    
3180                 }                                                                                        
3181             });                                                                                          
3182         }                                                                                                
3183     }                                                                                                    
3184                                                                                                          
3185     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
3186     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
3187         PackageManager packageManager = context.getPackageManager();                                     
3188         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
3189         widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());       
3190                                                                                                          
3191         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
3192         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
3193         Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));             
3194         return widgetsAndShortcuts;                                                                      
3195     }                                                                                                    
3196                                                                                                          
3197     private static boolean isPackageDisabled(Context context, String packageName,                        
3198             UserHandleCompat user) {                                                                     
3199         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
3200         return !launcherApps.isPackageEnabledForProfile(packageName, user);                              
3201     }                                                                                                    
3202                                                                                                          
3203     public static boolean isValidPackageActivity(Context context, ComponentName cn,                      
3204             UserHandleCompat user) {                                                                     
3205         if (cn == null) {                                                                                
3206             return false;                                                                                
3207         }                                                                                                
3208         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
3209         if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {                       
3210             return false;                                                                                
3211         }                                                                                                
3212         return launcherApps.isActivityEnabledForProfile(cn, user);                                       
3213     }                                                                                                    
3214                                                                                                          
3215     public static boolean isValidPackage(Context context, String packageName,                            
3216             UserHandleCompat user) {                                                                     
3217         if (packageName == null) {                                                                       
3218             return false;                                                                                
3219         }                                                                                                
3220         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
3221         return launcherApps.isPackageEnabledForProfile(packageName, user);                               
3222     }                                                                                                    
3223                                                                                                          
3224     /**                                                                                                  
3225      * Make an ShortcutInfo object for a restored application or shortcut item that points               
3226      * to a package that is not yet installed on the system.                                             
3227      */                                                                                                  
3228     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,                
3229             int promiseType) {                                                                           
3230         final ShortcutInfo info = new ShortcutInfo();                                                    
3231         info.user = UserHandleCompat.myUserHandle();                                                     
3232         mIconCache.getTitleAndIcon(info, intent, info.user, true);                                       
3233                                                                                                          
3234         if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {                                      
3235             String title = (cursor != null) ? cursor.getString(titleIndex) : null;                       
3236             if (!TextUtils.isEmpty(title)) {                                                             
3237                 info.title = title;                                                                      
3238             }                                                                                            
3239             info.status = ShortcutInfo.FLAG_RESTORED_ICON;                                               
3240         } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {                            
3241             if (TextUtils.isEmpty(info.title)) {                                                         
3242                 info.title = (cursor != null) ? cursor.getString(titleIndex) : "";                       
3243             }                                                                                            
3244             info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;                                             
3245         } else {                                                                                         
3246             throw new InvalidParameterException("Invalid restoreType " + promiseType);                   
3247         }                                                                                                
3248                                                                                                          
3249         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
3250                 info.title.toString(), info.user);                                                       
3251         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
3252         info.promisedIntent = intent;                                                                    
3253         return info;                                                                                     
3254     }                                                                                                    
3255                                                                                                          
3256     /**                                                                                                  
3257      * Make an Intent object for a restored application or shortcut item that points                     
3258      * to the market page for the item.                                                                  
3259      */                                                                                                  
3260     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
3261         ComponentName componentName = intent.getComponent();                                             
3262         return getMarketIntent(componentName.getPackageName());                                          
3263     }                                                                                                    
3264                                                                                                          
3265     static Intent getMarketIntent(String packageName) {                                                  
3266         return new Intent(Intent.ACTION_VIEW)                                                            
3267             .setData(new Uri.Builder()                                                                   
3268                 .scheme("market")                                                                        
3269                 .authority("details")                                                                    
3270                 .appendQueryParameter("id", packageName)                                                 
3271                 .build());                                                                               
3272     }                                                                                                    
3273                                                                                                          
3274     /**                                                                                                  
3275      * This is called from the code that adds shortcuts from the intent receiver.  This                  
3276      * doesn't have a Cursor, but                                                                        
3277      */                                                                                                  
3278     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                           
3279             UserHandleCompat user, Context context) {                                                    
3280         return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);               
3281     }                                                                                                    
3282                                                                                                          
3283     /**                                                                                                  
3284      * Make an ShortcutInfo object for a shortcut that is an application.                                
3285      *                                                                                                   
3286      * If c is not null, then it will be used to fill in missing data like the title and icon.           
3287      */                                                                                                  
3288     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                           
3289             UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,             
3290             HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {                      
3291         if (user == null) {                                                                              
3292             Log.d(TAG, "Null user found in getShortcutInfo");                                            
3293             return null;                                                                                 
3294         }                                                                                                
3295                                                                                                          
3296         ComponentName componentName = intent.getComponent();                                             
3297         if (componentName == null) {                                                                     
3298             Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);                  
3299             return null;                                                                                 
3300         }                                                                                                
3301                                                                                                          
3302         Intent newIntent = new Intent(intent.getAction(), null);                                         
3303         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
3304         newIntent.setComponent(componentName);                                                           
3305         LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);                 
3306         if ((lai == null) && !allowMissingTarget) {                                                      
3307             Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);                   
3308             return null;                                                                                 
3309         }                                                                                                
3310                                                                                                          
3311         final ShortcutInfo info = new ShortcutInfo();                                                    
3312                                                                                                          
3313         // the resource -- This may implicitly give us back the fallback icon,                           
3314         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
3315         // to avoid saving lots of copies of that in the database, and most apps                         
3316         // have icons anyway.                                                                            
3317         Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);                                
3318                                                                                                          
3319         // the db                                                                                        
3320         if (icon == null) {                                                                              
3321             if (c != null) {                                                                             
3322                 icon = getIconFromCursor(c, iconIndex, context);                                         
3323             }                                                                                            
3324         }                                                                                                
3325         // the fallback icon                                                                             
3326         if (icon == null) {                                                                              
3327             icon = mIconCache.getDefaultIcon(user);                                                      
3328             info.usingFallbackIcon = true;                                                               
3329         }                                                                                                
3330         info.setIcon(icon);                                                                              
3331                                                                                                          
3332         // From the cache.                                                                               
3333         if (labelCache != null) {                                                                        
3334             info.title = labelCache.get(componentName);                                                  
3335         }                                                                                                
3336                                                                                                          
3337         // from the resource                                                                             
3338         if (info.title == null && lai != null) {                                                         
3339             info.title = lai.getLabel();                                                                 
3340             if (labelCache != null) {                                                                    
3341                 labelCache.put(componentName, info.title);                                               
3342             }                                                                                            
3343         }                                                                                                
3344         // from the db                                                                                   
3345         if (info.title == null) {                                                                        
3346             if (c != null) {                                                                             
3347                 info.title =  c.getString(titleIndex);                                                   
3348             }                                                                                            
3349         }                                                                                                
3350         // fall back to the class name of the activity                                                   
3351         if (info.title == null) {                                                                        
3352             info.title = componentName.getClassName();                                                   
3353         }                                                                                                
3354         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
3355         info.user = user;                                                                                
3356         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
3357                 info.title.toString(), info.user);                                                       
3358         return info;                                                                                     
3359     }                                                                                                    
3360                                                                                                          
3361     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                               
3362             ItemInfoFilter f) {                                                                          
3363         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
3364         for (ItemInfo i : infos) {                                                                       
3365             if (i instanceof ShortcutInfo) {                                                             
3366                 ShortcutInfo info = (ShortcutInfo) i;                                                    
3367                 ComponentName cn = info.getTargetComponent();                                            
3368                 if (cn != null && f.filterItem(null, info, cn)) {                                        
3369                     filtered.add(info);                                                                  
3370                 }                                                                                        
3371             } else if (i instanceof FolderInfo) {                                                        
3372                 FolderInfo info = (FolderInfo) i;                                                        
3373                 for (ShortcutInfo s : info.contents) {                                                   
3374                     ComponentName cn = s.getTargetComponent();                                           
3375                     if (cn != null && f.filterItem(info, s, cn)) {                                       
3376                         filtered.add(s);                                                                 
3377                     }                                                                                    
3378                 }                                                                                        
3379             } else if (i instanceof LauncherAppWidgetInfo) {                                             
3380                 LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                  
3381                 ComponentName cn = info.providerName;                                                    
3382                 if (cn != null && f.filterItem(null, info, cn)) {                                        
3383                     filtered.add(info);                                                                  
3384                 }                                                                                        
3385             }                                                                                            
3386         }                                                                                                
3387         return new ArrayList<ItemInfo>(filtered);                                                        
3388     }                                                                                                    
3389                                                                                                          
3390     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,                   
3391             final UserHandleCompat user) {                                                               
3392         ItemInfoFilter filter  = new ItemInfoFilter() {                                                  
3393             @Override                                                                                    
3394             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
3395                 if (info.user == null) {                                                                 
3396                     return cn.equals(cname);                                                             
3397                 } else {                                                                                 
3398                     return cn.equals(cname) && info.user.equals(user);                                   
3399                 }                                                                                        
3400             }                                                                                            
3401         };                                                                                               
3402         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
3403     }                                                                                                    
3404                                                                                                          
3405     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
3406         if (i instanceof ShortcutInfo) {                                                                 
3407             ShortcutInfo info = (ShortcutInfo) i;                                                        
3408             // We need to check for ACTION_MAIN otherwise getComponent() might                           
3409             // return null for some shortcuts (for instance, for shortcuts to                            
3410             // web pages.)                                                                               
3411             Intent intent = info.intent;                                                                 
3412             ComponentName name = intent.getComponent();                                                  
3413             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                     
3414                     Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                     
3415                 return true;                                                                             
3416             }                                                                                            
3417             // placeholder shortcuts get special treatment, let them through too.                        
3418             if (info.isPromise()) {                                                                      
3419                 return true;                                                                             
3420             }                                                                                            
3421         }                                                                                                
3422         return false;                                                                                    
3423     }                                                                                                    
3424                                                                                                          
3425     /**                                                                                                  
3426      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
3427      */                                                                                                  
3428     private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                      
3429             int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,               
3430             int titleIndex) {                                                                            
3431                                                                                                          
3432         Bitmap icon = null;                                                                              
3433         final ShortcutInfo info = new ShortcutInfo();                                                    
3434         // Non-app shortcuts are only supported for current user.                                        
3435         info.user = UserHandleCompat.myUserHandle();                                                     
3436         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
3437                                                                                                          
3438         // TODO: If there's an explicit component and we can't install that, delete it.                  
3439                                                                                                          
3440         info.title = c.getString(titleIndex);                                                            
3441                                                                                                          
3442         int iconType = c.getInt(iconTypeIndex);                                                          
3443         switch (iconType) {                                                                              
3444         case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                              
3445             String packageName = c.getString(iconPackageIndex);                                          
3446             String resourceName = c.getString(iconResourceIndex);                                        
3447             PackageManager packageManager = context.getPackageManager();                                 
3448             info.customIcon = false;                                                                     
3449             // the resource                                                                              
3450             try {                                                                                        
3451                 Resources resources = packageManager.getResourcesForApplication(packageName);            
3452                 if (resources != null) {                                                                 
3453                     final int id = resources.getIdentifier(resourceName, null, null);                    
3454                     icon = Utilities.createIconBitmap(                                                   
3455                             mIconCache.getFullResIcon(resources, id), context);                          
3456                 }                                                                                        
3457             } catch (Exception e) {                                                                      
3458                 // drop this.  we have other places to look for icons                                    
3459             }                                                                                            
3460             // the db                                                                                    
3461             if (icon == null) {                                                                          
3462                 icon = getIconFromCursor(c, iconIndex, context);                                         
3463             }                                                                                            
3464             // the fallback icon                                                                         
3465             if (icon == null) {                                                                          
3466                 icon = mIconCache.getDefaultIcon(info.user);                                             
3467                 info.usingFallbackIcon = true;                                                           
3468             }                                                                                            
3469             break;                                                                                       
3470         case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                
3471             icon = getIconFromCursor(c, iconIndex, context);                                             
3472             if (icon == null) {                                                                          
3473                 icon = mIconCache.getDefaultIcon(info.user);                                             
3474                 info.customIcon = false;                                                                 
3475                 info.usingFallbackIcon = true;                                                           
3476             } else {                                                                                     
3477                 info.customIcon = true;                                                                  
3478             }                                                                                            
3479             break;                                                                                       
3480         default:                                                                                         
3481             icon = mIconCache.getDefaultIcon(info.user);                                                 
3482             info.usingFallbackIcon = true;                                                               
3483             info.customIcon = false;                                                                     
3484             break;                                                                                       
3485         }                                                                                                
3486         info.setIcon(icon);                                                                              
3487         return info;                                                                                     
3488     }                                                                                                    
3489                                                                                                          
3490     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
3491         @SuppressWarnings("all") // suppress dead code warning                                           
3492         final boolean debug = false;                                                                     
3493         if (debug) {                                                                                     
3494             Log.d(TAG, "getIconFromCursor app="                                                          
3495                     + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));           
3496         }                                                                                                
3497         byte[] data = c.getBlob(iconIndex);                                                              
3498         try {                                                                                            
3499             return Utilities.createIconBitmap(                                                           
3500                     BitmapFactory.decodeByteArray(data, 0, data.length), context);                       
3501         } catch (Exception e) {                                                                          
3502             return null;                                                                                 
3503         }                                                                                                
3504     }                                                                                                    
3505                                                                                                          
3506     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                   
3507             int cellX, int cellY, boolean notify) {                                                      
3508         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
3509         if (info == null) {                                                                              
3510             return null;                                                                                 
3511         }                                                                                                
3512         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
3513                                                                                                          
3514         return info;                                                                                     
3515     }                                                                                                    
3516                                                                                                          
3517     /**                                                                                                  
3518      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
3519      */                                                                                                  
3520     static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                 
3521             ComponentName component) {                                                                   
3522         List<AppWidgetProviderInfo> widgets =                                                            
3523             AppWidgetManager.getInstance(context).getInstalledProviders();                               
3524         for (AppWidgetProviderInfo info : widgets) {                                                     
3525             if (info.provider.equals(component)) {                                                       
3526                 return info;                                                                             
3527             }                                                                                            
3528         }                                                                                                
3529         return null;                                                                                     
3530     }                                                                                                    
3531                                                                                                          
3532     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
3533         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
3534         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
3535         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
3536                                                                                                          
3537         if (intent == null) {                                                                            
3538             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
3539             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
3540             return null;                                                                                 
3541         }                                                                                                
3542                                                                                                          
3543         Bitmap icon = null;                                                                              
3544         boolean customIcon = false;                                                                      
3545         ShortcutIconResource iconResource = null;                                                        
3546                                                                                                          
3547         if (bitmap != null && bitmap instanceof Bitmap) {                                                
3548             icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);          
3549             customIcon = true;                                                                           
3550         } else {                                                                                         
3551             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
3552             if (extra != null && extra instanceof ShortcutIconResource) {                                
3553                 try {                                                                                    
3554                     iconResource = (ShortcutIconResource) extra;                                         
3555                     final PackageManager packageManager = context.getPackageManager();                   
3556                     Resources resources = packageManager.getResourcesForApplication(                     
3557                             iconResource.packageName);                                                   
3558                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
3559                     icon = Utilities.createIconBitmap(                                                   
3560                             mIconCache.getFullResIcon(resources, id),                                    
3561                             context);                                                                    
3562                 } catch (Exception e) {                                                                  
3563                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
3564                 }                                                                                        
3565             }                                                                                            
3566         }                                                                                                
3567                                                                                                          
3568         final ShortcutInfo info = new ShortcutInfo();                                                    
3569                                                                                                          
3570         // Only support intents for current user for now. Intents sent from other                        
3571         // users wouldn't get here without intent forwarding anyway.                                     
3572         info.user = UserHandleCompat.myUserHandle();                                                     
3573         if (icon == null) {                                                                              
3574             if (fallbackIcon != null) {                                                                  
3575                 icon = fallbackIcon;                                                                     
3576             } else {                                                                                     
3577                 icon = mIconCache.getDefaultIcon(info.user);                                             
3578                 info.usingFallbackIcon = true;                                                           
3579             }                                                                                            
3580         }                                                                                                
3581         info.setIcon(icon);                                                                              
3582                                                                                                          
3583         info.title = name;                                                                               
3584         info.contentDescription = mUserManager.getBadgedLabelForUser(                                    
3585                 info.title.toString(), info.user);                                                       
3586         info.intent = intent;                                                                            
3587         info.customIcon = customIcon;                                                                    
3588         info.iconResource = iconResource;                                                                
3589                                                                                                          
3590         return info;                                                                                     
3591     }                                                                                                    
3592                                                                                                          
3593     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,             
3594             int iconIndex) {                                                                             
3595         // If apps can't be on SD, don't even bother.                                                    
3596         if (!mAppsCanBeOnRemoveableStorage) {                                                            
3597             return false;                                                                                
3598         }                                                                                                
3599         // If this icon doesn't have a custom icon, check to see                                         
3600         // what's stored in the DB, and if it doesn't match what                                         
3601         // we're going to show, store what we are going to show back                                     
3602         // into the DB.  We do this so when we're loading, if the                                        
3603         // package manager can't find an icon (for example because                                       
3604         // the app is on SD) then we can use that instead.                                               
3605         if (!info.customIcon && !info.usingFallbackIcon) {                                               
3606             cache.put(info, c.getBlob(iconIndex));                                                       
3607             return true;                                                                                 
3608         }                                                                                                
3609         return false;                                                                                    
3610     }                                                                                                    
3611     void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {                              
3612         boolean needSave = false;                                                                        
3613         try {                                                                                            
3614             if (data != null) {                                                                          
3615                 Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);                      
3616                 Bitmap loaded = info.getIcon(mIconCache);                                                
3617                 needSave = !saved.sameAs(loaded);                                                        
3618             } else {                                                                                     
3619                 needSave = true;                                                                         
3620             }                                                                                            
3621         } catch (Exception e) {                                                                          
3622             needSave = true;                                                                             
3623         }                                                                                                
3624         if (needSave) {                                                                                  
3625             Log.d(TAG, "going to save icon bitmap for info=" + info);                                    
3626             // This is slower than is ideal, but this only happens once                                  
3627             // or when the app is updated with a new icon.                                               
3628             updateItemInDatabase(context, info);                                                         
3629         }                                                                                                
3630     }                                                                                                    
3631                                                                                                          
3632     /**                                                                                                  
3633      * Return an existing FolderInfo object if we have encountered this ID previously,                   
3634      * or make a new one.                                                                                
3635      */                                                                                                  
3636     private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {             
3637         // See if a placeholder was created for us already                                               
3638         FolderInfo folderInfo = folders.get(id);                                                         
3639         if (folderInfo == null) {                                                                        
3640             // No placeholder -- create a new instance                                                   
3641             folderInfo = new FolderInfo();                                                               
3642             folders.put(id, folderInfo);                                                                 
3643         }                                                                                                
3644         return folderInfo;                                                                               
3645     }                                                                                                    
3646                                                                                                          
3647     public static final Comparator<AppInfo> getAppNameComparator() {                                     
3648         final Collator collator = Collator.getInstance();                                                
3649         return new Comparator<AppInfo>() {                                                               
3650             public final int compare(AppInfo a, AppInfo b) {                                             
3651                 if (a.user.equals(b.user)) {                                                             
3652                     int result = collator.compare(a.title.toString().trim(),                             
3653                             b.title.toString().trim());                                                  
3654                     if (result == 0) {                                                                   
3655                         result = a.componentName.compareTo(b.componentName);                             
3656                     }                                                                                    
3657                     return result;                                                                       
3658                 } else {                                                                                 
3659                     // TODO Need to figure out rules for sorting                                         
3660                     // profiles, this puts work second.                                                  
3661                     return a.user.toString().compareTo(b.user.toString());                               
3662                 }                                                                                        
3663             }                                                                                            
3664         };                                                                                               
3665     }                                                                                                    
3666     public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR                                  
3667             = new Comparator<AppInfo>() {                                                                
3668         public final int compare(AppInfo a, AppInfo b) {                                                 
3669             if (a.firstInstallTime < b.firstInstallTime) return 1;                                       
3670             if (a.firstInstallTime > b.firstInstallTime) return -1;                                      
3671             return 0;                                                                                    
3672         }                                                                                                
3673     };                                                                                                   
3674     static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {                             
3675         if (info.activityInfo != null) {                                                                 
3676             return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);             
3677         } else {                                                                                         
3678             return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);               
3679         }                                                                                                
3680     }                                                                                                    
3681     public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {       
3682         private Collator mCollator;                                                                      
3683         private HashMap<Object, CharSequence> mLabelCache;                                               
3684         ShortcutNameComparator(PackageManager pm) {                                                      
3685             mLabelCache = new HashMap<Object, CharSequence>();                                           
3686             mCollator = Collator.getInstance();                                                          
3687         }                                                                                                
3688         ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {                               
3689             mLabelCache = labelCache;                                                                    
3690             mCollator = Collator.getInstance();                                                          
3691         }                                                                                                
3692         public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {           
3693             String labelA, labelB;                                                                       
3694             ComponentName keyA = a.getComponentName();                                                   
3695             ComponentName keyB = b.getComponentName();                                                   
3696             if (mLabelCache.containsKey(keyA)) {                                                         
3697                 labelA = mLabelCache.get(keyA).toString();                                               
3698             } else {                                                                                     
3699                 labelA = a.getLabel().toString().trim();                                                 
3700                                                                                                          
3701                 mLabelCache.put(keyA, labelA);                                                           
3702             }                                                                                            
3703             if (mLabelCache.containsKey(keyB)) {                                                         
3704                 labelB = mLabelCache.get(keyB).toString();                                               
3705             } else {                                                                                     
3706                 labelB = b.getLabel().toString().trim();                                                 
3707                                                                                                          
3708                 mLabelCache.put(keyB, labelB);                                                           
3709             }                                                                                            
3710             return mCollator.compare(labelA, labelB);                                                    
3711         }                                                                                                
3712     };                                                                                                   
3713     public static class WidgetAndShortcutNameComparator implements Comparator<Object> {                  
3714         private final AppWidgetManagerCompat mManager;                                                   
3715         private final PackageManager mPackageManager;                                                    
3716         private final HashMap<Object, String> mLabelCache;                                               
3717         private final Collator mCollator;                                                                
3718                                                                                                          
3719         WidgetAndShortcutNameComparator(Context context) {                                               
3720             mManager = AppWidgetManagerCompat.getInstance(context);                                      
3721             mPackageManager = context.getPackageManager();                                               
3722             mLabelCache = new HashMap<Object, String>();                                                 
3723             mCollator = Collator.getInstance();                                                          
3724         }                                                                                                
3725         public final int compare(Object a, Object b) {                                                   
3726             String labelA, labelB;                                                                       
3727             if (mLabelCache.containsKey(a)) {                                                            
3728                 labelA = mLabelCache.get(a);                                                             
3729             } else {                                                                                     
3730                 labelA = (a instanceof AppWidgetProviderInfo)                                            
3731                         ? mManager.loadLabel((AppWidgetProviderInfo) a)                                  
3732                         : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();                
3733                 mLabelCache.put(a, labelA);                                                              
3734             }                                                                                            
3735             if (mLabelCache.containsKey(b)) {                                                            
3736                 labelB = mLabelCache.get(b);                                                             
3737             } else {                                                                                     
3738                 labelB = (b instanceof AppWidgetProviderInfo)                                            
3739                         ? mManager.loadLabel((AppWidgetProviderInfo) b)                                  
3740                         : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();                
3741                 mLabelCache.put(b, labelB);                                                              
3742             }                                                                                            
3743             return mCollator.compare(labelA, labelB);                                                    
3744         }                                                                                                
3745     };                                                                                                   
3746                                                                                                          
3747     static boolean isValidProvider(AppWidgetProviderInfo provider) {                                     
3748         return (provider != null) && (provider.provider != null)                                         
3749                 && (provider.provider.getPackageName() != null);                                         
3750     }                                                                                                    
3751                                                                                                          
3752     public void dumpState() {                                                                            
3753         Log.d(TAG, "mCallbacks=" + mCallbacks);                                                          
3754         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);                  
3755         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);                
3756         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);            
3757         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);          
3758         if (mLoaderTask != null) {                                                                       
3759             mLoaderTask.dumpState();                                                                     
3760         } else {                                                                                         
3761             Log.d(TAG, "mLoaderTask=null");                                                              
3762         }                                                                                                
3763     }                                                                                                    
3764 }                                                                                                        




























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































   1 /*                                                                                                       
   2  * Copyright (C) 2008 The Android Open Source Project                                                    
   3  *                                                                                                       
   4  * Licensed under the Apache License, Version 2.0 (the "License");                                       
   5  * you may not use this file except in compliance with the License.                                      
   6  * You may obtain a copy of the License at                                                               
   7  *                                                                                                       
   8  *      http://www.apache.org/licenses/LICENSE-2.0                                                       
   9  *                                                                                                       
  10  * Unless required by applicable law or agreed to in writing, software                                   
  11  * distributed under the License is distributed on an "AS IS" BASIS,                                     
  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                              
  13  * See the License for the specific language governing permissions and                                   
  14  * limitations under the License.                                                                        
  15  */                                                                                                      
  16 package com.android.launcher3;                                                                           
  17                                                                                                          
  18 import android.app.SearchManager;                                                                        
  19 import android.appwidget.AppWidgetManager;                                                               
  20 import android.appwidget.AppWidgetProviderInfo;                                                          
  21 import android.content.BroadcastReceiver;                                                                
  22 import android.content.ComponentName;                                                                    
  23 import android.content.ContentProviderClient;                                                            
  24 import android.content.ContentProviderOperation;                                                         
  25 import android.content.ContentResolver;                                                                  
  26 import android.content.ContentValues;                                                                    
  27 import android.content.Context;                                                                          
  28 import android.content.Intent.ShortcutIconResource;                                                      
  29 import android.content.Intent;                                                                           
  30 import android.content.IntentFilter;                                                                     
  31 import android.content.SharedPreferences;                                                                
  32 import android.content.pm.PackageManager;                                                                
  33 import android.content.pm.ProviderInfo;                                                                  
  34 import android.content.pm.ResolveInfo;                                                                   
  35 import android.content.res.Configuration;                                                                
  36 import android.content.res.Resources;                                                                    
  37 import android.database.Cursor;                                                                          
  38 import android.graphics.Bitmap;                                                                          
  39 import android.graphics.BitmapFactory;                                                                   
  40 import android.net.Uri;                                                                                  
  41 import android.os.Environment;                                                                           
  42 import android.os.Handler;                                                                               
  43 import android.os.HandlerThread;                                                                         
  44 import android.os.Parcelable;                                                                            
  45 import android.os.Process;                                                                               
  46 import android.os.RemoteException;                                                                       
  47 import android.os.SystemClock;                                                                           
  48 import android.provider.BaseColumns;                                                                     
  49 import android.text.TextUtils;                                                                           
  50 import android.util.Log;                                                                                 
  51 import android.util.Pair;                                                                                
  52 import com.android.launcher3.compat.AppWidgetManagerCompat;                                              
  53 import com.android.launcher3.compat.LauncherActivityInfoCompat;                                          
  54 import com.android.launcher3.compat.LauncherAppsCompat;                                                  
  55 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;                           
  56 import com.android.launcher3.compat.PackageInstallerCompat;                                              
  57 import com.android.launcher3.compat.UserHandleCompat;                                                    
  58 import com.android.launcher3.compat.UserManagerCompat;                                                   
  59 import java.lang.ref.WeakReference;                                                                      
  60 import java.net.URISyntaxException;                                                                      
  61 import java.security.InvalidParameterException;                                                          
  62 import java.text.Collator;                                                                               
  63 import java.util.ArrayList;                                                                              
  64 import java.util.Arrays;                                                                                 
  65 import java.util.Collection;                                                                             
  66 import java.util.Collections;                                                                            
  67 import java.util.Comparator;                                                                             
  68 import java.util.HashMap;                                                                                
  69 import java.util.HashSet;                                                                                
  70 import java.util.Iterator;                                                                               
  71 import java.util.List;                                                                                   
  72 import java.util.Map.Entry;                                                                              
  73 import java.util.Set;                                                                                    
  74 import java.util.TreeMap;                                                                                
  75 import java.util.concurrent.atomic.AtomicBoolean;                                                        
  76                                                                                                          
  77                                                                                                          
  78 /**                                                                                                      
  79  * Maintains in-memory state of the Launcher. It is expected that there should be only one               
  80  * LauncherModel object held in a static. Also provide APIs for updating the database state              
  81  * for the Launcher.                                                                                     
  82  */                                                                                                      
  83 public class LauncherModel extends BroadcastReceiver implements LauncherAppsCompat.OnAppsChangedCallbackC🔵
  84     static final boolean DEBUG_LOADERS = false;                                                          
  85                                                                                                          
  86     private static final boolean DEBUG_RECEIVER = false;                                                 
  87                                                                                                          
  88     private static final boolean REMOVE_UNRESTORED_ICONS = true;                                         
  89                                                                                                          
  90     static final String TAG = "Launcher.Model";                                                          
  91                                                                                                          
  92     // true = use a "More Apps" folder for non-workspace apps on upgrade                                 
  93     // false = strew non-workspace apps across the workspace on upgrade                                  
  94     // true = use a "More Apps" folder for non-workspace apps on upgrade                                 
  95     // false = strew non-workspace apps across the workspace on upgrade                                  
  96     public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;                                    
  97                                                                                                          
  98     public static final int LOADER_FLAG_NONE = 0;                                                        
  99                                                                                                          
 100     public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;                                        
 101                                                                                                          
 102     public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;                                      
 103                                                                                                          
 104     // batch size for the workspace icons                                                                
 105     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons                      
 106                                                                                                          
 107     private static final long INVALID_SCREEN_ID = -1L;                                                   
 108                                                                                                          
 109     private final boolean mAppsCanBeOnRemoveableStorage;                                                 
 110                                                                                                          
 111     private final boolean mOldContentProviderExists;                                                     
 112                                                                                                          
 113     private final LauncherAppState mApp;                                                                 
 114                                                                                                          
 115     private final Object mLock = new Object();                                                           
 116                                                                                                          
 117     private DeferredHandler mHandler = new DeferredHandler();                                            
 118                                                                                                          
 119     private LoaderTask mLoaderTask;                                                                      
 120                                                                                                          
 121     private boolean mIsLoaderTaskRunning;                                                                
 122                                                                                                          
 123     private volatile boolean mFlushingWorkerThread;                                                      
 124                                                                                                          
 125     // Specific runnable types that are run on the main thread deferred handler, this allows us to       
 126     // clear all queued binding runnables when the Launcher activity is destroyed.                       
 127     private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;                                            
 128                                                                                                          
 129     private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;                                           
 130                                                                                                          
 131     private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";                    
 132                                                                                                          
 133     private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");             
 134                                                                                                          
 135     static {                                                                                             
 136         sWorkerThread.start();                                                                           
 137     }                                                                                                    
 138                                                                                                          
 139     private static final Handler sWorker = new Handler(sWorkerThread.getLooper());                       
 140                                                                                                          
 141     // We start off with everything not loaded.  After that, we assume that                              
 142     // our monitoring of the package manager provides all updates and we never                           
 143     // need to do a requery.  These are only ever touched from the loader thread.                        
 144     private boolean mWorkspaceLoaded;                                                                    
 145                                                                                                          
 146     private boolean mAllAppsLoaded;                                                                      
 147                                                                                                          
 148     // When we are loading pages synchronously, we can't just post the binding of items on the side      
 149     // pages as this delays the rotation process.  Instead, we wait for a callback from the first        
 150     // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start       
 151     // a normal load, we also clear this set of Runnables.                                               
 152     static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();                 
 153                                                                                                          
 154     private WeakReference<Callbacks> mCallbacks;                                                         
 155                                                                                                          
 156     // < only access in worker thread >                                                                  
 157     // < only access in worker thread >                                                                  
 158     AllAppsList mBgAllAppsList;                                                                          
 159                                                                                                          
 160     // The lock that must be acquired before referencing any static bg data structures.  Unlike          
 161     // other locks, this one can generally be held long-term because we never expect any of these        
 162     // static data structures to be referenced outside of the worker thread except on the first          
 163     // load after configuration change.                                                                  
 164     static final Object sBgLock = new Object();                                                          
 165                                                                                                          
 166     // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by               
 167     // LauncherModel to their ids                                                                        
 168     static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();                  
 169                                                                                                          
 170     // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts       
 171     //       created by LauncherModel that are directly on the home screen (however, no widgets or       
 172     //       shortcuts within folders).                                                                  
 173     static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();                      
 174                                                                                                          
 175     // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()    
 176     static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
 177                                                                                                          
 178     // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()                   
 179     static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();                 
 180                                                                                                          
 181     // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database      
 182     static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();                 
 183                                                                                                          
 184     // sBgWorkspaceScreens is the ordered set of workspace screens.                                      
 185     // sBgWorkspaceScreens is the ordered set of workspace screens.                                      
 186     static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();                            
 187                                                                                                          
 188     // sPendingPackages is a set of packages which could be on sdcard and are not available yet          
 189     static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages = new HashMap<UserHandleComp🔵
 190                                                                                                          
 191     // </ only access in worker thread >                                                                 
 192     // </ only access in worker thread >                                                                 
 193                                                                                                          
 194     private IconCache mIconCache;                                                                        
 195                                                                                                          
 196     protected int mPreviousConfigMcc;                                                                    
 197                                                                                                          
 198     private final LauncherAppsCompat mLauncherApps;                                                      
 199                                                                                                          
 200     private final UserManagerCompat mUserManager;                                                        
 201                                                                                                          
 202     public interface Callbacks {                                                                         
 203         public boolean setLoadOnResume();                                                                
 204                                                                                                          
 205         public int getCurrentWorkspaceScreen();                                                          
 206                                                                                                          
 207         public void startBinding();                                                                      
 208                                                                                                          
 209         public abstract void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end, boolean forceAn🔵
 210                                                                                                          
 211         public void bindScreens(ArrayList<Long> orderedScreenIds);                                       
 212                                                                                                          
 213         public void bindAddScreens(ArrayList<Long> orderedScreenIds);                                    
 214                                                                                                          
 215         public abstract void bindFolders(HashMap<Long, FolderInfo> folders);                             
 216                                                                                                          
 217         public void finishBindingItems(boolean upgradePath);                                             
 218                                                                                                          
 219         public abstract void bindAppWidget(LauncherAppWidgetInfo info);                                  
 220                                                                                                          
 221         public abstract void bindAllApplications(ArrayList<AppInfo> apps);                               
 222                                                                                                          
 223         public abstract void bindAppsAdded(ArrayList<Long> newScreens, ArrayList<ItemInfo> addNotAnimated🔵
 224                                                                                                          
 225         public abstract void bindAppsUpdated(ArrayList<AppInfo> apps);                                   
 226                                                                                                          
 227         public void bindAppsRestored(ArrayList<AppInfo> apps);                                           
 228                                                                                                          
 229         public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);                       
 230                                                                                                          
 231         public void updatePackageBadge(String packageName);                                              
 232                                                                                                          
 233         public abstract void bindComponentsRemoved(ArrayList<String> packageNames, ArrayList<AppInfo> app🔵
 234                                                                                                          
 235         public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);                          
 236                                                                                                          
 237         public void bindSearchablesChanged();                                                            
 238                                                                                                          
 239         public boolean isAllAppsButtonRank(int rank);                                                    
 240                                                                                                          
 241         public void onPageBoundSynchronously(int page);                                                  
 242                                                                                                          
 243         public void dumpLogsToLocalData();                                                               
 244     }                                                                                                    
 245                                                                                                          
 246     public interface ItemInfoFilter {                                                                    
 247         public abstract boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);            
 248     }                                                                                                    
 249                                                                                                          
 250     LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {                      
 251         Context context = app.getContext();                                                              
 252         mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();                        
 253         String oldProvider = context.getString(R.string.old_launcher_provider_uri);                      
 254         // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different               
 255         // resource string.                                                                              
 256         String redirectAuthority = Uri.parse(oldProvider).getAuthority();                                
 257         ProviderInfo providerInfo = context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY,🔵
 258         ProviderInfo redirectProvider = context.getPackageManager().resolveContentProvider(redirectAuthor🔵
 259         Log.d(TAG, "Old launcher provider: " + oldProvider);                                             
 260         mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);                
 261         if (mOldContentProviderExists) {                                                                 
 262             Log.d(TAG, "Old launcher provider exists.");                                                 
 263         } else {                                                                                         
 264             Log.d(TAG, "Old launcher provider does not exist.");                                         
 265         }                                                                                                
 266         mApp = app;                                                                                      
 267         mBgAllAppsList = new AllAppsList(iconCache, appFilter);                                          
 268         mIconCache = iconCache;                                                                          
 269         final Resources res = context.getResources();                                                    
 270         Configuration config = res.getConfiguration();                                                   
 271         mPreviousConfigMcc = config.mcc;                                                                 
 272         mLauncherApps = LauncherAppsCompat.getInstance(context);                                         
 273         mUserManager = UserManagerCompat.getInstance(context);                                           
 274     }                                                                                                    
 275                                                                                                          
 276     /** Runs the specified runnable immediately if called from the main thread, otherwise it is          
 277      * posted on the main thread handler. */                                                             
 278     private void runOnMainThread(Runnable r) {                                                           
 279         runOnMainThread(r, 0);                                                                           
 280     }                                                                                                    
 281                                                                                                          
 282     private void runOnMainThread(Runnable r, int type) {                                                 
 283         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 284             // If we are on the worker thread, post onto the main handler                                
 285             mHandler.post(r);                                                                            
 286         } else {                                                                                         
 287             r.run();                                                                                     
 288         }                                                                                                
 289     }                                                                                                    
 290                                                                                                          
 291     /** Runs the specified runnable immediately if called from the worker thread, otherwise it is        
 292      * posted on the worker thread handler. */                                                           
 293     private static void runOnWorkerThread(Runnable r) {                                                  
 294         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 295             r.run();                                                                                     
 296         } else {                                                                                         
 297             // If we are not on the worker thread, then post to the worker handler                       
 298             sWorker.post(r);                                                                             
 299         }                                                                                                
 300     }                                                                                                    
 301                                                                                                          
 302     boolean canMigrateFromOldLauncherDb(Launcher launcher) {                                             
 303         return mOldContentProviderExists && (!launcher.isLauncherPreinstalled());                        
 304     }                                                                                                    
 305                                                                                                          
 306     static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy, long screen) {
 307         LauncherAppState app = LauncherAppState.getInstance();                                           
 308         DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                    
 309         final int xCount = ((int) (grid.numColumns));                                                    
 310         final int yCount = ((int) (grid.numRows));                                                       
 311         boolean[][] occupied = new boolean[xCount][yCount];                                              
 312         int cellX;                                                                                       
 313         int cellY;                                                                                       
 314         int spanX;                                                                                       
 315         int spanY;                                                                                       
 316         for (int i = 0; i < items.size(); ++i) {                                                         
 317             final ItemInfo item = items.get(i);                                                          
 318             if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                        
 319                 if (item.screenId == screen) {                                                           
 320                     cellX = item.cellX;                                                                  
 321                     cellY = item.cellY;                                                                  
 322                     spanX = item.spanX;                                                                  
 323                     spanY = item.spanY;                                                                  
 324                     for (int x = cellX; ((0 <= x) && (x < (cellX + spanX))) && (x < xCount); x++) {      
 325                         for (int y = cellY; ((0 <= y) && (y < (cellY + spanY))) && (y < yCount); y++) {  
 326                             occupied[x][y] = true;                                                       
 327                         }                                                                                
 328                     }                                                                                    
 329                 }                                                                                        
 330             }                                                                                            
 331         }                                                                                                
 332         return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);                            
 333     }                                                                                                    
 334                                                                                                          
 335     static Pair<Long, int[]> findNextAvailableIconSpace(Context context, String name, Intent launchIntent🔵
 336         // Lock on the app so that we don't try and get the items while apps are being added             
 337         LauncherAppState app = LauncherAppState.getInstance();                                           
 338         LauncherModel model = app.getModel();                                                            
 339         boolean found = false;                                                                           
 340         synchronized(app) {                                                                              
 341             if (sWorkerThread.getThreadId() != Process.myTid()) {                                        
 342                 // Flush the LauncherModel worker thread, so that if we just did another                 
 343                 // processInstallShortcut, we give it time for its shortcut to get added to the          
 344                 // database (getItemsInLocalCoordinates reads the database)                              
 345                 model.flushWorkerThread();                                                               
 346             }                                                                                            
 347             final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);         
 348             // Try adding to the workspace screens incrementally, starting at the default or center      
 349             // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))       
 350             firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size());                      
 351             int count = workspaceScreens.size();                                                         
 352             for (int screen = firstScreenIndex; (screen < count) && (!found); screen++) {                
 353                 int[] tmpCoordinates = new int[2];                                                       
 354                 if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates, workspaceScreens.get(screen🔵
 355                     // Update the Launcher db                                                            
 356                     return new Pair<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);          
 357                 }                                                                                        
 358             }                                                                                            
 359         }                                                                                                
 360         return null;                                                                                     
 361     }                                                                                                    
 362                                                                                                          
 363     public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {                       
 364         // Process the updated package state                                                             
 365         Runnable r = new Runnable() {                                                                    
 366             public void run() {                                                                          
 367                 Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;                    
 368                 if (callbacks != null) {                                                                 
 369                     callbacks.updatePackageState(installInfo);                                           
 370                 }                                                                                        
 371             }                                                                                            
 372         };                                                                                               
 373         mHandler.post(r);                                                                                
 374     }                                                                                                    
 375                                                                                                          
 376     public void updatePackageBadge(final String packageName) {                                           
 377         // Process the updated package badge                                                             
 378         Runnable r = new Runnable() {                                                                    
 379             public void run() {                                                                          
 380                 Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;                    
 381                 if (callbacks != null) {                                                                 
 382                     callbacks.updatePackageBadge(packageName);                                           
 383                 }                                                                                        
 384             }                                                                                            
 385         };                                                                                               
 386         mHandler.post(r);                                                                                
 387     }                                                                                                    
 388                                                                                                          
 389     public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {              
 390         final Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;                      
 391         if (allAppsApps == null) {                                                                       
 392             throw new RuntimeException("allAppsApps must not be null");                                  
 393         }                                                                                                
 394         if (allAppsApps.isEmpty()) {                                                                     
 395             return;                                                                                      
 396         }                                                                                                
 397         final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                           
 398         Iterator<AppInfo> iter = allAppsApps.iterator();                                                 
 399         while (iter.hasNext()) {                                                                         
 400             ItemInfo a = iter.next();                                                                    
 401             if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {                               
 402                 restoredAppsFinal.add(((AppInfo) (a)));                                                  
 403             }                                                                                            
 404         }                                                                                                
 405         // Process the newly added applications and add them to the database first                       
 406         Runnable r = new Runnable() {                                                                    
 407             public void run() {                                                                          
 408                 runOnMainThread(new Runnable() {                                                         
 409                     public void run() {                                                                  
 410                         Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;                   
 411                         if ((callbacks == cb) && (cb != null)) {                                         
 412                             if (!restoredAppsFinal.isEmpty()) {                                          
 413                                 for (AppInfo info : restoredAppsFinal) {                                 
 414                                     final Intent intent = info.getIntent();                              
 415                                     if (intent != null) {                                                
 416                                         mIconCache.deletePreloadedIcon(intent.getComponent(), info.user);
 417                                     }                                                                    
 418                                 }                                                                        
 419                                 callbacks.bindAppsUpdated(restoredAppsFinal);                            
 420                             }                                                                            
 421                             callbacks.bindAppsAdded(null, null, null, allAppsApps);                      
 422                         }                                                                                
 423                     }                                                                                    
 424                 });                                                                                      
 425             }                                                                                            
 426         };                                                                                               
 427         runOnWorkerThread(r);                                                                            
 428     }                                                                                                    
 429                                                                                                          
 430     public void addAndBindAddedWorkspaceApps(final Context context, final ArrayList<ItemInfo> workspaceAp🔵
 431         final Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;                      
 432         if (workspaceApps == null) {                                                                     
 433             throw new RuntimeException("workspaceApps and allAppsApps must not be null");                
 434         }                                                                                                
 435         if (workspaceApps.isEmpty()) {                                                                   
 436             return;                                                                                      
 437         }                                                                                                
 438         // Process the newly added applications and add them to the database first                       
 439         Runnable r = new Runnable() {                                                                    
 440             public void run() {                                                                          
 441                 final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();               
 442                 final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                
 443                 final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                   
 444                 // Get the list of workspace screens.  We need to append to this list and                
 445                 // can not use sBgWorkspaceScreens because loadWorkspace() may not have been             
 446                 // called.                                                                               
 447                 ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                
 448                 TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                 
 449                 for (Integer i : orderedScreens.keySet()) {                                              
 450                     long screenId = orderedScreens.get(i);                                               
 451                     workspaceScreens.add(screenId);                                                      
 452                 }                                                                                        
 453                 synchronized(sBgLock) {                                                                  
 454                     Iterator<ItemInfo> iter = workspaceApps.iterator();                                  
 455                     while (iter.hasNext()) {                                                             
 456                         ItemInfo a = iter.next();                                                        
 457                         final String name = a.title.toString();                                          
 458                         final Intent launchIntent = a.getIntent();                                       
 459                         // Short-circuit this logic if the icon exists somewhere on the workspace        
 460                         if (LauncherModel.shortcutExists(context, name, launchIntent)) {                 
 461                             // Only InstallShortcutReceiver sends us shortcutInfos, ignore them          
 462                             if ((a instanceof AppInfo) && LauncherModel.appWasPromise(context, launchInte🔵
 463                                 restoredAppsFinal.add(((AppInfo) (a)));                                  
 464                             }                                                                            
 465                             continue;                                                                    
 466                         }                                                                                
 467                         // Add this icon to the db, creating a new page if necessary.  If there          
 468                         // is only the empty page then we just add items to the first page.              
 469                         // Otherwise, we add them to the next pages.                                     
 470                         int startSearchPageIndex = (workspaceScreens.isEmpty()) ? 0 : 1;                 
 471                         Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context, name🔵
 472                         if (coords == null) {                                                            
 473                             LauncherProvider lp = LauncherAppState.getLauncherProvider();                
 474                             // If we can't find a valid position, then just add a new screen.            
 475                             // This takes time so we need to re-queue the add until the new              
 476                             // page is added.  Create as many screens as necessary to satisfy            
 477                             // the startSearchPageIndex.                                                 
 478                             int numPagesToAdd = Math.max(1, (startSearchPageIndex + 1) - workspaceScreens🔵
 479                             while (numPagesToAdd > 0) {                                                  
 480                                 long screenId = lp.generateNewScreenId();                                
 481                                 // Save the screen id for binding in the workspace                       
 482                                 workspaceScreens.add(screenId);                                          
 483                                 addedWorkspaceScreensFinal.add(screenId);                                
 484                                 numPagesToAdd--;                                                         
 485                             }                                                                            
 486                             // Find the coordinate again                                                 
 487                             coords = LauncherModel.findNextAvailableIconSpace(context, name, launchIntent🔵
 488                         }                                                                                
 489                         if (coords == null) {                                                            
 490                             throw new RuntimeException("Coordinates should not be null");                
 491                         }                                                                                
 492                         ShortcutInfo shortcutInfo;                                                       
 493                         if (a instanceof ShortcutInfo) {                                                 
 494                             shortcutInfo = ((ShortcutInfo) (a));                                         
 495                         } else if (a instanceof AppInfo) {                                               
 496                             shortcutInfo = ((AppInfo) (a)).makeShortcut();                               
 497                         } else {                                                                         
 498                             throw new RuntimeException("Unexpected info type");                          
 499                         }                                                                                
 500                         // Add the shortcut to the db                                                    
 501                         addItemToDatabase(context, shortcutInfo, LauncherSettings.Favorites.CONTAINER_DES🔵
 502                         // Save the ShortcutInfo for binding in the workspace                            
 503                         addedShortcutsFinal.add(shortcutInfo);                                           
 504                     }                                                                                    
 505                 }                                                                                        
 506                 // Update the workspace screens                                                          
 507                 updateWorkspaceScreenOrder(context, workspaceScreens);                                   
 508                 if (!addedShortcutsFinal.isEmpty()) {                                                    
 509                     runOnMainThread(new Runnable() {                                                     
 510                         public void run() {                                                              
 511                             Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;               
 512                             if ((callbacks == cb) && (cb != null)) {                                     
 513                                 final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();       
 514                                 final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();    
 515                                 if (!addedShortcutsFinal.isEmpty()) {                                    
 516                                     ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 🔵
 517                                     long lastScreenId = info.screenId;                                   
 518                                     for (ItemInfo i : addedShortcutsFinal) {                             
 519                                         if (i.screenId == lastScreenId) {                                
 520                                             addAnimated.add(i);                                          
 521                                         } else {                                                         
 522                                             addNotAnimated.add(i);                                       
 523                                         }                                                                
 524                                     }                                                                    
 525                                 }                                                                        
 526                                 callbacks.bindAppsAdded(addedWorkspaceScreensFinal, addNotAnimated, addAn🔵
 527                                 if (!restoredAppsFinal.isEmpty()) {                                      
 528                                     callbacks.bindAppsUpdated(restoredAppsFinal);                        
 529                                 }                                                                        
 530                             }                                                                            
 531                         }                                                                                
 532                     });                                                                                  
 533                 }                                                                                        
 534             }                                                                                            
 535         };                                                                                               
 536         runOnWorkerThread(r);                                                                            
 537     }                                                                                                    
 538                                                                                                          
 539     public void unbindItemInfosAndClearQueuedBindRunnables() {                                           
 540         if (sWorkerThread.getThreadId() == Process.myTid()) {                                            
 541             throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " + "mai🔵
 542         }                                                                                                
 543         // Clear any deferred bind runnables                                                             
 544         synchronized(mDeferredBindRunnables) {                                                           
 545             mDeferredBindRunnables.clear();                                                              
 546         }                                                                                                
 547         // Remove any queued bind runnables                                                              
 548         mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);                                 
 549         // Unbind all the workspace items                                                                
 550         unbindWorkspaceItemsOnMainThread();                                                              
 551     }                                                                                                    
 552                                                                                                          
 553     /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */                        
 554     void unbindWorkspaceItemsOnMainThread() {                                                            
 555         // Ensure that we don't use the same workspace items data structure on the main thread           
 556         // by making a copy of workspace items first.                                                    
 557         final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();                         
 558         final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();                             
 559         synchronized(sBgLock) {                                                                          
 560             tmpWorkspaceItems.addAll(sBgWorkspaceItems);                                                 
 561             tmpAppWidgets.addAll(sBgAppWidgets);                                                         
 562         }                                                                                                
 563         Runnable r = new Runnable() {                                                                    
 564             @Override                                                                                    
 565             public void run() {                                                                          
 566                 for (ItemInfo item : tmpWorkspaceItems) {                                                
 567                     item.unbind();                                                                       
 568                 }                                                                                        
 569                 for (ItemInfo item : tmpAppWidgets) {                                                    
 570                     item.unbind();                                                                       
 571                 }                                                                                        
 572             }                                                                                            
 573         };                                                                                               
 574         runOnMainThread(r);                                                                              
 575     }                                                                                                    
 576                                                                                                          
 577     /**                                                                                                  
 578      * Adds an item to the DB if it was not created previously, or move it to a new                      
 579      * <container, screen, cellX, cellY>                                                                 
 580      */                                                                                                  
 581     static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container, long screenId, in🔵
 582         if (item.container == ItemInfo.NO_ID) {                                                          
 583             // From all apps                                                                             
 584             addItemToDatabase(context, item, container, screenId, cellX, cellY, false);                  
 585         } else {                                                                                         
 586             // From somewhere else                                                                       
 587             moveItemInDatabase(context, item, container, screenId, cellX, cellY);                        
 588         }                                                                                                
 589     }                                                                                                    
 590                                                                                                          
 591     static void checkItemInfoLocked(final long itemId, final ItemInfo item, StackTraceElement[] stackTrac🔵
 592         ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                                  
 593         if ((modelItem != null) && (item != modelItem)) {                                                
 594             // check all the data is consistent                                                          
 595             if ((modelItem instanceof ShortcutInfo) && (item instanceof ShortcutInfo)) {                 
 596                 ShortcutInfo modelShortcut = ((ShortcutInfo) (modelItem));                               
 597                 ShortcutInfo shortcut = ((ShortcutInfo) (item));                                         
 598                 if ((((((((((modelShortcut.title.toString().equals(shortcut.title.toString()) && modelSho🔵
 599                     // For all intents and purposes, this is the same object                             
 600                     return;                                                                              
 601                 }                                                                                        
 602             }                                                                                            
 603             // the modelItem needs to match up perfectly with item if our model is                       
 604             // to be consistent with the database-- for now, just require                                
 605             // modelItem == item or the equality check above                                             
 606             String msg = ((("item: " + (item != null ? item.toString() : "null")) + "modelItem: ") + (mod🔵
 607             RuntimeException e = new RuntimeException(msg);                                              
 608             if (stackTrace != null) {                                                                    
 609                 e.setStackTrace(stackTrace);                                                             
 610             }                                                                                            
 611             throw e;                                                                                     
 612         }                                                                                                
 613     }                                                                                                    
 614                                                                                                          
 615     static void checkItemInfo(final ItemInfo item) {                                                     
 616         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 617         final long itemId = item.id;                                                                     
 618         Runnable r = new Runnable() {                                                                    
 619             public void run() {                                                                          
 620                 synchronized(sBgLock) {                                                                  
 621                     checkItemInfoLocked(itemId, item, stackTrace);                                       
 622                 }                                                                                        
 623             }                                                                                            
 624         };                                                                                               
 625         runOnWorkerThread(r);                                                                            
 626     }                                                                                                    
 627                                                                                                          
 628     static void updateItemInDatabaseHelper(Context context, final ContentValues values, final ItemInfo it🔵
 629         final long itemId = item.id;                                                                     
 630         final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);                         
 631         final ContentResolver cr = context.getContentResolver();                                         
 632         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 633         Runnable r = new Runnable() {                                                                    
 634             public void run() {                                                                          
 635                 cr.update(uri, values, null, null);                                                      
 636                 updateItemArrays(item, itemId, stackTrace);                                              
 637             }                                                                                            
 638         };                                                                                               
 639         runOnWorkerThread(r);                                                                            
 640     }                                                                                                    
 641                                                                                                          
 642     static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList, f🔵
 643         final ContentResolver cr = context.getContentResolver();                                         
 644         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 645         Runnable r = new Runnable() {                                                                    
 646             public void run() {                                                                          
 647                 ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();     
 648                 int count = items.size();                                                                
 649                 for (int i = 0; i < count; i++) {                                                        
 650                     ItemInfo item = items.get(i);                                                        
 651                     final long itemId = item.id;                                                         
 652                     final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);             
 653                     ContentValues values = valuesList.get(i);                                            
 654                     ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());         
 655                     updateItemArrays(item, itemId, stackTrace);                                          
 656                 }                                                                                        
 657                 try {                                                                                    
 658                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
 659                 } catch (java.lang.Exception e) {                                                        
 660                     e.printStackTrace();                                                                 
 661                 }                                                                                        
 662             }                                                                                            
 663         };                                                                                               
 664         runOnWorkerThread(r);                                                                            
 665     }                                                                                                    
 666                                                                                                          
 667     static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {           
 668         // Lock on mBgLock *after* the db operation                                                      
 669         synchronized(sBgLock) {                                                                          
 670             checkItemInfoLocked(itemId, item, stackTrace);                                               
 671             if ((item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) && (item.container != La🔵
 672                 // Item is in a folder, make sure this folder exists                                     
 673                 if (!sBgFolders.containsKey(item.container)) {                                           
 674                     // An items container is being set to a that of an item which is not in              
 675                     // the list of Folders.                                                              
 676                     String msg = ((("item: " + item) + " container being set to: ") + item.container) + "🔵
 677                     Log.e(TAG, msg);                                                                     
 678                 }                                                                                        
 679             }                                                                                            
 680             // Items are added/removed from the corresponding FolderInfo elsewhere, such                 
 681             // as in Workspace.onDrop. Here, we just add/remove them from the list of items              
 682             // that are on the desktop, as appropriate                                                   
 683             ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                              
 684             if ((modelItem != null) && ((modelItem.container == LauncherSettings.Favorites.CONTAINER_DESK🔵
 685                 switch (modelItem.itemType) {                                                            
 686                     case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION :                              
 687                     case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT :                                 
 688                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER :                                   
 689                         if (!sBgWorkspaceItems.contains(modelItem)) {                                    
 690                             sBgWorkspaceItems.add(modelItem);                                            
 691                         }                                                                                
 692                         break;                                                                           
 693                     default :                                                                            
 694                         break;                                                                           
 695                 }                                                                                        
 696             } else {                                                                                     
 697                 sBgWorkspaceItems.remove(modelItem);                                                     
 698             }                                                                                            
 699         }                                                                                                
 700     }                                                                                                    
 701                                                                                                          
 702     public void flushWorkerThread() {                                                                    
 703         mFlushingWorkerThread = true;                                                                    
 704         Runnable waiter = new Runnable() {                                                               
 705                 public void run() {                                                                      
 706                     synchronized (this) {                                                                
 707                         notifyAll();                                                                     
 708                         mFlushingWorkerThread = false;                                                   
 709                     }                                                                                    
 710                 }                                                                                        
 711             };                                                                                           
 712                                                                                                          
 713         synchronized(waiter) {                                                                           
 714             runOnWorkerThread(waiter);                                                                   
 715             if (mLoaderTask != null) {                                                                   
 716                 synchronized(mLoaderTask) {                                                              
 717                     mLoaderTask.notify();                                                                
 718                 }                                                                                        
 719             }                                                                                            
 720             boolean success = false;                                                                     
 721             while (!success) {                                                                           
 722                 try {                                                                                    
 723                     waiter.wait();                                                                       
 724                     success = true;                                                                      
 725                 } catch (InterruptedException e) {                                                       
 726                 }                                                                                        
 727             }                                                                                            
 728         }                                                                                                
 729     }                                                                                                    
 730                                                                                                          
 731     /**                                                                                                  
 732      * Move an item in the DB to a new <container, screen, cellX, cellY>                                 
 733      */                                                                                                  
 734     static void moveItemInDatabase(Context context, final ItemInfo item, final long container, final long🔵
 735         item.container = container;                                                                      
 736         item.cellX = cellX;                                                                              
 737         item.cellY = cellY;                                                                              
 738         // We store hotseat items in canonical form which is this orientation invariant position         
 739         // in the hotseat                                                                                
 740         if (((context instanceof Launcher) && (screenId < 0)) && (container == LauncherSettings.Favorites🔵
 741             item.screenId = ((Launcher) (context)).getHotseat().getOrderInHotseat(cellX, cellY);         
 742         } else {                                                                                         
 743             item.screenId = screenId;                                                                    
 744         }                                                                                                
 745         final ContentValues values = new ContentValues();                                                
 746         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
 747         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
 748         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
 749         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
 750         updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");                         
 751     }                                                                                                    
 752                                                                                                          
 753     /**                                                                                                  
 754      * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the               
 755      * cellX, cellY have already been updated on the ItemInfos.                                          
 756      */                                                                                                  
 757     static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items, final long containe🔵
 758         ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();                         
 759         int count = items.size();                                                                        
 760         for (int i = 0; i < count; i++) {                                                                
 761             ItemInfo item = items.get(i);                                                                
 762             item.container = container;                                                                  
 763             // We store hotseat items in canonical form which is this orientation invariant position     
 764             // in the hotseat                                                                            
 765             if (((context instanceof Launcher) && (screen < 0)) && (container == LauncherSettings.Favorit🔵
 766                 item.screenId = ((Launcher) (context)).getHotseat().getOrderInHotseat(item.cellX, item.ce🔵
 767             } else {                                                                                     
 768                 item.screenId = screen;                                                                  
 769             }                                                                                            
 770             final ContentValues values = new ContentValues();                                            
 771             values.put(LauncherSettings.Favorites.CONTAINER, item.container);                            
 772             values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                    
 773             values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                    
 774             values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                
 775             contentValues.add(values);                                                                   
 776         }                                                                                                
 777         updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");                
 778     }                                                                                                    
 779                                                                                                          
 780     /**                                                                                                  
 781      * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>        
 782      */                                                                                                  
 783     static void modifyItemInDatabase(Context context, final ItemInfo item, final long container, final lo🔵
 784         item.container = container;                                                                      
 785         item.cellX = cellX;                                                                              
 786         item.cellY = cellY;                                                                              
 787         item.spanX = spanX;                                                                              
 788         item.spanY = spanY;                                                                              
 789         // We store hotseat items in canonical form which is this orientation invariant position         
 790         // in the hotseat                                                                                
 791         if (((context instanceof Launcher) && (screenId < 0)) && (container == LauncherSettings.Favorites🔵
 792             item.screenId = ((Launcher) (context)).getHotseat().getOrderInHotseat(cellX, cellY);         
 793         } else {                                                                                         
 794             item.screenId = screenId;                                                                    
 795         }                                                                                                
 796         final ContentValues values = new ContentValues();                                                
 797         values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                
 798         values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                        
 799         values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                        
 800         values.put(LauncherSettings.Favorites.SPANX, item.spanX);                                        
 801         values.put(LauncherSettings.Favorites.SPANY, item.spanY);                                        
 802         values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                    
 803         updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");                       
 804     }                                                                                                    
 805                                                                                                          
 806     /**                                                                                                  
 807      * Update an item to the database in a specified container.                                          
 808      */                                                                                                  
 809     static void updateItemInDatabase(Context context, final ItemInfo item) {                             
 810         final ContentValues values = new ContentValues();                                                
 811         item.onAddToDatabase(context, values);                                                           
 812         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
 813         updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");                       
 814     }                                                                                                    
 815                                                                                                          
 816     /**                                                                                                  
 817      * Returns true if the shortcuts already exists in the database.                                     
 818      * we identify a shortcut by its title and intent.                                                   
 819      */                                                                                                  
 820     static boolean shortcutExists(Context context, String title, Intent intent) {                        
 821         final ContentResolver cr = context.getContentResolver();                                         
 822         final Intent intentWithPkg;                                                                      
 823         final Intent intentWithoutPkg;                                                                   
 824         if (intent.getComponent() != null) {                                                             
 825             // If component is not null, an intent with null package will produce                        
 826             // the same result and should also be a match.                                               
 827             if (intent.getPackage() != null) {                                                           
 828                 intentWithPkg = intent;                                                                  
 829                 intentWithoutPkg = new Intent(intent).setPackage(null);                                  
 830             } else {                                                                                     
 831                 intentWithPkg = new Intent(intent).setPackage(intent.getComponent().getPackageName());   
 832                 intentWithoutPkg = intent;                                                               
 833             }                                                                                            
 834         } else {                                                                                         
 835             intentWithPkg = intent;                                                                      
 836             intentWithoutPkg = intent;                                                                   
 837         }                                                                                                
 838         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[]{ "title", "intent" }, "t🔵
 839         boolean result = false;                                                                          
 840         try {                                                                                            
 841             result = c.moveToFirst();                                                                    
 842         } finally {                                                                                      
 843             c.close();                                                                                   
 844         }                                                                                                
 845         return result;                                                                                   
 846     }                                                                                                    
 847                                                                                                          
 848     /**                                                                                                  
 849      * Returns true if the promise shortcuts with the same package name exists on the workspace.         
 850      */                                                                                                  
 851     static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {                
 852         final ComponentName component = intent.getComponent();                                           
 853         if (component == null) {                                                                         
 854             return false;                                                                                
 855         }                                                                                                
 856         return !getItemsByPackageName(component.getPackageName(), user).isEmpty();                       
 857     }                                                                                                    
 858                                                                                                          
 859     /**                                                                                                  
 860      * Returns an ItemInfo array containing all the items in the LauncherModel.                          
 861      * The ItemInfo.id is not set through this function.                                                 
 862      */                                                                                                  
 863     static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {                             
 864         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
 865         final ContentResolver cr = context.getContentResolver();                                         
 866         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[]{ LauncherSettings.Favori🔵
 867         final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);         
 868         final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);        
 869         final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);              
 870         final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                
 871         final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                
 872         final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);                
 873         final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);                
 874         final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);       
 875         UserManagerCompat userManager = UserManagerCompat.getInstance(context);                          
 876         try {                                                                                            
 877             while (c.moveToNext()) {                                                                     
 878                 ItemInfo item = new ItemInfo();                                                          
 879                 item.cellX = c.getInt(cellXIndex);                                                       
 880                 item.cellY = c.getInt(cellYIndex);                                                       
 881                 item.spanX = Math.max(1, c.getInt(spanXIndex));                                          
 882                 item.spanY = Math.max(1, c.getInt(spanYIndex));                                          
 883                 item.container = c.getInt(containerIndex);                                               
 884                 item.itemType = c.getInt(itemTypeIndex);                                                 
 885                 item.screenId = c.getInt(screenIndex);                                                   
 886                 long serialNumber = c.getInt(profileIdIndex);                                            
 887                 item.user = userManager.getUserForSerialNumber(serialNumber);                            
 888                 // Skip if user has been deleted.                                                        
 889                 if (item.user != null) {                                                                 
 890                     items.add(item);                                                                     
 891                 }                                                                                        
 892             }                                                                                            
 893         } catch (java.lang.Exception e) {                                                                
 894             items.clear();                                                                               
 895         } finally {                                                                                      
 896             c.close();                                                                                   
 897         }                                                                                                
 898         return items;                                                                                    
 899     }                                                                                                    
 900                                                                                                          
 901     /**                                                                                                  
 902      * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.       
 903      */                                                                                                  
 904     FolderInfo getFolderById(Context context, HashMap<Long, FolderInfo> folderList, long id) {           
 905         final ContentResolver cr = context.getContentResolver();                                         
 906         Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null, "_id=? and (itemType=? or itemT🔵
 907         try {                                                                                            
 908             if (c.moveToFirst()) {                                                                       
 909                 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); 
 910                 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);        
 911                 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
 912                 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);      
 913                 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);        
 914                 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);        
 915                 FolderInfo folderInfo = null;                                                            
 916                 switch (c.getInt(itemTypeIndex)) {                                                       
 917                     case LauncherSettings.Favorites.ITEM_TYPE_FOLDER :                                   
 918                         folderInfo = findOrMakeFolder(folderList, id);                                   
 919                         break;                                                                           
 920                 }                                                                                        
 921                 folderInfo.title = c.getString(titleIndex);                                              
 922                 folderInfo.id = id;                                                                      
 923                 folderInfo.container = c.getInt(containerIndex);                                         
 924                 folderInfo.screenId = c.getInt(screenIndex);                                             
 925                 folderInfo.cellX = c.getInt(cellXIndex);                                                 
 926                 folderInfo.cellY = c.getInt(cellYIndex);                                                 
 927                 return folderInfo;                                                                       
 928             }                                                                                            
 929         } finally {                                                                                      
 930             c.close();                                                                                   
 931         }                                                                                                
 932         return null;                                                                                     
 933     }                                                                                                    
 934                                                                                                          
 935     /**                                                                                                  
 936      * Add an item to the database in a specified container. Sets the container, screen, cellX and       
 937      * cellY fields of the item. Also assigns an ID to the item.                                         
 938      */                                                                                                  
 939     static void addItemToDatabase(Context context, final ItemInfo item, final long container, final long 🔵
 940         item.container = container;                                                                      
 941         item.cellX = cellX;                                                                              
 942         item.cellY = cellY;                                                                              
 943         // We store hotseat items in canonical form which is this orientation invariant position         
 944         // in the hotseat                                                                                
 945         if (((context instanceof Launcher) && (screenId < 0)) && (container == LauncherSettings.Favorites🔵
 946             item.screenId = ((Launcher) (context)).getHotseat().getOrderInHotseat(cellX, cellY);         
 947         } else {                                                                                         
 948             item.screenId = screenId;                                                                    
 949         }                                                                                                
 950         final ContentValues values = new ContentValues();                                                
 951         final ContentResolver cr = context.getContentResolver();                                         
 952         item.onAddToDatabase(context, values);                                                           
 953         item.id = LauncherAppState.getLauncherProvider().generateNewItemId();                            
 954         values.put(LauncherSettings.Favorites._ID, item.id);                                             
 955         item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                
 956         final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                          
 957         Runnable r = new Runnable() {                                                                    
 958             public void run() {                                                                          
 959                 cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI : LauncherSettings.Favorites.CO🔵
 960                 // Lock on mBgLock *after* the db operation                                              
 961                 synchronized(sBgLock) {                                                                  
 962                     checkItemInfoLocked(item.id, item, stackTrace);                                      
 963                     sBgItemsIdMap.put(item.id, item);                                                    
 964                     switch (item.itemType) {                                                             
 965                         case LauncherSettings.Favorites.ITEM_TYPE_FOLDER :                               
 966                             sBgFolders.put(item.id, ((FolderInfo) (item)));                              
 967                             // Fall through                                                              
 968                         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION :                          
 969                         case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT :                             
 970                             if ((item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) || (item🔵
 971                                 sBgWorkspaceItems.add(item);                                             
 972                             } else if (!sBgFolders.containsKey(item.container)) {                        
 973                                 // Adding an item to a folder that doesn't exist.                        
 974                                 String msg = (("adding item: " + item) + " to a folder that ") + " doesn'🔵
 975                                 Log.e(TAG, msg);                                                         
 976                             }                                                                            
 977                             break;                                                                       
 978                         case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET :                            
 979                             sBgAppWidgets.add(((LauncherAppWidgetInfo) (item)));                         
 980                             break;                                                                       
 981                     }                                                                                    
 982                 }                                                                                        
 983             }                                                                                            
 984         };                                                                                               
 985         runOnWorkerThread(r);                                                                            
 986     }                                                                                                    
 987                                                                                                          
 988     /**                                                                                                  
 989      * Creates a new unique child id, for a given cell span across all layouts.                          
 990      */                                                                                                  
 991     static int getCellLayoutChildId(                                                                     
 992             long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {         
 993         return (((int) container & 0xFF) << 24)                                                          
 994                 | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);          
 995     }                                                                                                    
 996                                                                                                          
 997     private static ArrayList<ItemInfo> getItemsByPackageName(final String pn, final UserHandleCompat user🔵
 998         ItemInfoFilter filter = new ItemInfoFilter() {                                                   
 999             @Override                                                                                    
1000             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
1001                 return cn.getPackageName().equals(pn) && info.user.equals(user);                         
1002             }                                                                                            
1003         };                                                                                               
1004         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
1005     }                                                                                                    
1006                                                                                                          
1007     /**                                                                                                  
1008      * Removes all the items from the database corresponding to the specified package.                   
1009      */                                                                                                  
1010     static void deletePackageFromDatabase(Context context, final String pn,                              
1011             final UserHandleCompat user) {                                                               
1012         deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));                               
1013     }                                                                                                    
1014                                                                                                          
1015     /**                                                                                                  
1016      * Removes the specified item from the database                                                      
1017      * @param context                                                                                    
1018      * @param item                                                                                       
1019      */                                                                                                  
1020     static void deleteItemFromDatabase(Context context, final ItemInfo item) {                           
1021         ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                           
1022         items.add(item);                                                                                 
1023         deleteItemsFromDatabase(context, items);                                                         
1024     }                                                                                                    
1025                                                                                                          
1026     /**                                                                                                  
1027      * Removes the specified items from the database                                                     
1028      * @param context                                                                                    
1029      * @param item                                                                                       
1030      */                                                                                                  
1031     static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {              
1032         final ContentResolver cr = context.getContentResolver();                                         
1033         Runnable r = new Runnable() {                                                                    
1034             public void run() {                                                                          
1035                 for (ItemInfo item : items) {                                                            
1036                     final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);            
1037                     cr.delete(uri, null, null);                                                          
1038                 // Lock on mBgLock *after* the db operation                                              
1039                     synchronized(sBgLock) {                                                              
1040                         switch (item.itemType) {                                                         
1041                             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER :                           
1042                                 sBgFolders.remove(item.id);                                              
1043                                 for (ItemInfo info : sBgItemsIdMap.values()) {                           
1044                                     if (info.container == item.id) {                                     
1045                                     // We are deleting a folder which still contains items that          
1046                                     // think they are contained by that folder.                          
1047                                         String msg = (((("deleting a folder (" + item) + ") which still "🔵
1048                                         Log.e(TAG, msg);                                                 
1049                                     }                                                                    
1050                                 }                                                                        
1051                                 sBgWorkspaceItems.remove(item);                                          
1052                                 break;                                                                   
1053                             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION :                      
1054                             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT :                         
1055                                 sBgWorkspaceItems.remove(item);                                          
1056                                 break;                                                                   
1057                             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET :                        
1058                                 sBgAppWidgets.remove(((LauncherAppWidgetInfo) (item)));                  
1059                                 break;                                                                   
1060                         }                                                                                
1061                         sBgItemsIdMap.remove(item.id);                                                   
1062                         sBgDbIconCache.remove(item);                                                     
1063                     }                                                                                    
1064                 }                                                                                        
1065             }                                                                                            
1066         };                                                                                               
1067         runOnWorkerThread(r);                                                                            
1068     }                                                                                                    
1069                                                                                                          
1070     /**                                                                                                  
1071      * Update the order of the workspace screens in the database. The array list contains                
1072      * a list of screen ids in the order that they should appear.                                        
1073      */                                                                                                  
1074     void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {                    
1075         // Log to disk                                                                                   
1076         Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);                       
1077         Launcher.addDumpLog(TAG, "11683562 -   screens: " + TextUtils.join(", ", screens), true);        
1078         final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);                                
1079         final ContentResolver cr = context.getContentResolver();                                         
1080         final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                                   
1081         // Remove any negative screen ids -- these aren't persisted                                      
1082         Iterator<Long> iter = screensCopy.iterator();                                                    
1083         while (iter.hasNext()) {                                                                         
1084             long id = iter.next();                                                                       
1085             if (id < 0) {                                                                                
1086                 iter.remove();                                                                           
1087             }                                                                                            
1088         }                                                                                                
1089         Runnable r = new Runnable() {                                                                    
1090             @Override                                                                                    
1091             public void run() {                                                                          
1092                 ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();     
1093                 // Clear the table                                                                       
1094                 ops.add(ContentProviderOperation.newDelete(uri).build());                                
1095                 int count = screensCopy.size();                                                          
1096                 for (int i = 0; i < count; i++) {                                                        
1097                     ContentValues v = new ContentValues();                                               
1098                     long screenId = screensCopy.get(i);                                                  
1099                     v.put(LauncherSettings.WorkspaceScreens._ID, screenId);                              
1100                     v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);                             
1101                     ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());              
1102                 }                                                                                        
1103                 try {                                                                                    
1104                     cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                      
1105                 } catch (java.lang.Exception ex) {                                                       
1106                     throw new RuntimeException(ex);                                                      
1107                 }                                                                                        
1108                 synchronized(sBgLock) {                                                                  
1109                     sBgWorkspaceScreens.clear();                                                         
1110                     sBgWorkspaceScreens.addAll(screensCopy);                                             
1111                 }                                                                                        
1112             }                                                                                            
1113         };                                                                                               
1114         runOnWorkerThread(r);                                                                            
1115     }                                                                                                    
1116                                                                                                          
1117     /**                                                                                                  
1118      * Remove the contents of the specified folder from the database                                     
1119      */                                                                                                  
1120     static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {               
1121         final ContentResolver cr = context.getContentResolver();                                         
1122         Runnable r = new Runnable() {                                                                    
1123             public void run() {                                                                          
1124                 cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);         
1125                 // Lock on mBgLock *after* the db operation                                              
1126                 synchronized(sBgLock) {                                                                  
1127                     sBgItemsIdMap.remove(info.id);                                                       
1128                     sBgFolders.remove(info.id);                                                          
1129                     sBgDbIconCache.remove(info);                                                         
1130                     sBgWorkspaceItems.remove(info);                                                      
1131                 }                                                                                        
1132                 cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, (LauncherSettings.Favor🔵
1133                 // Lock on mBgLock *after* the db operation                                              
1134                 synchronized(sBgLock) {                                                                  
1135                     for (ItemInfo childInfo : info.contents) {                                           
1136                         sBgItemsIdMap.remove(childInfo.id);                                              
1137                         sBgDbIconCache.remove(childInfo);                                                
1138                     }                                                                                    
1139                 }                                                                                        
1140             }                                                                                            
1141         };                                                                                               
1142         runOnWorkerThread(r);                                                                            
1143     }                                                                                                    
1144                                                                                                          
1145     /**                                                                                                  
1146      * Set this as the current Launcher activity object for the loader.                                  
1147      */                                                                                                  
1148     public void initialize(Callbacks callbacks) {                                                        
1149         synchronized (mLock) {                                                                           
1150             mCallbacks = new WeakReference<Callbacks>(callbacks);                                        
1151         }                                                                                                
1152     }                                                                                                    
1153                                                                                                          
1154     @Override                                                                                            
1155     public void onPackageChanged(String packageName, UserHandleCompat user) {                            
1156         int op = PackageUpdatedTask.OP_UPDATE;                                                           
1157         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[]{ packageName }, user));            
1158     }                                                                                                    
1159                                                                                                          
1160     @Override                                                                                            
1161     public void onPackageRemoved(String packageName, UserHandleCompat user) {                            
1162         int op = PackageUpdatedTask.OP_REMOVE;                                                           
1163         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[]{ packageName }, user));            
1164     }                                                                                                    
1165                                                                                                          
1166     @Override                                                                                            
1167     public void onPackageAdded(String packageName, UserHandleCompat user) {                              
1168         int op = PackageUpdatedTask.OP_ADD;                                                              
1169         enqueuePackageUpdated(new PackageUpdatedTask(op, new String[]{ packageName }, user));            
1170     }                                                                                                    
1171                                                                                                          
1172     @Override                                                                                            
1173     public void onPackagesAvailable(String[] packageNames, UserHandleCompat user, boolean replacing) {   
1174         if (!replacing) {                                                                                
1175             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames, user));
1176             if (mAppsCanBeOnRemoveableStorage) {                                                         
1177                 // Only rebind if we support removable storage. It catches the                           
1178                 // case where                                                                            
1179                 // apps on the external sd card need to be reloaded                                      
1180                 startLoaderFromBackground();                                                             
1181             }                                                                                            
1182         } else {                                                                                         
1183             // If we are replacing then just update the packages in the list                             
1184             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, packageNames, user🔵
1185         }                                                                                                
1186     }                                                                                                    
1187                                                                                                          
1188     @Override                                                                                            
1189     public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user, boolean replacing) { 
1190         if (!replacing) {                                                                                
1191             enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UNAVAILABLE, packageNames,🔵
1192         }                                                                                                
1193     }                                                                                                    
1194                                                                                                          
1195     /**                                                                                                  
1196      * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and                        
1197      * ACTION_PACKAGE_CHANGED.                                                                           
1198      */                                                                                                  
1199     @Override                                                                                            
1200     public void onReceive(Context context, Intent intent) {                                              
1201         if (DEBUG_RECEIVER) {                                                                            
1202             Log.d(TAG, "onReceive intent=" + intent);                                                    
1203         }                                                                                                
1204         final String action = intent.getAction();                                                        
1205         if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {                                               
1206             // If we have changed locale we need to clear out the labels in all apps/workspace.          
1207             forceReload();                                                                               
1208         } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {                                 
1209             // Check if configuration change was an mcc/mnc change which would affect app resources      
1210             // and we would need to clear out the labels in all apps/workspace. Same handling as         
1211             // above for ACTION_LOCALE_CHANGED                                                           
1212             Configuration currentConfig = context.getResources().getConfiguration();                     
1213             if (mPreviousConfigMcc != currentConfig.mcc) {                                               
1214                 Log.d(TAG, (("Reload apps on config change. curr_mcc:" + currentConfig.mcc) + " prevmcc:"🔵
1215                 forceReload();                                                                           
1216             }                                                                                            
1217             // Update previousConfig                                                                     
1218             mPreviousConfigMcc = currentConfig.mcc;                                                      
1219         } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) || SearchManager.IN🔵
1220             if (mCallbacks != null) {                                                                    
1221                 Callbacks callbacks = mCallbacks.get();                                                  
1222                 if (callbacks != null) {                                                                 
1223                     callbacks.bindSearchablesChanged();                                                  
1224                 }                                                                                        
1225             }                                                                                            
1226         }                                                                                                
1227     }                                                                                                    
1228                                                                                                          
1229     void forceReload() {                                                                                 
1230         resetLoadedState(true, true);                                                                    
1231         // Do this here because if the launcher activity is running it will be restarted.                
1232         // If it's not running startLoaderFromBackground will merely tell it that it needs               
1233         // to reload.                                                                                    
1234         startLoaderFromBackground();                                                                     
1235     }                                                                                                    
1236                                                                                                          
1237     public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {             
1238         synchronized (mLock) {                                                                           
1239             // Stop any existing loaders first, so they don't set mAllAppsLoaded or                      
1240             // mWorkspaceLoaded to true later                                                            
1241             stopLoaderLocked();                                                                          
1242             if (resetAllAppsLoaded) mAllAppsLoaded = false;                                              
1243             if (resetWorkspaceLoaded) mWorkspaceLoaded = false;                                          
1244         }                                                                                                
1245     }                                                                                                    
1246                                                                                                          
1247     /**                                                                                                  
1248      * When the launcher is in the background, it's possible for it to miss paired                       
1249      * configuration changes.  So whenever we trigger the loader from the background                     
1250      * tell the launcher that it needs to re-run the loader when it comes back instead                   
1251      * of doing it now.                                                                                  
1252      */                                                                                                  
1253     public void startLoaderFromBackground() {                                                            
1254         boolean runLoader = false;                                                                       
1255         if (mCallbacks != null) {                                                                        
1256             Callbacks callbacks = mCallbacks.get();                                                      
1257             if (callbacks != null) {                                                                     
1258                 // Only actually run the loader if they're not paused.                                   
1259                 if (!callbacks.setLoadOnResume()) {                                                      
1260                     runLoader = true;                                                                    
1261                 }                                                                                        
1262             }                                                                                            
1263         }                                                                                                
1264         if (runLoader) {                                                                                 
1265             startLoader(false, PagedView.INVALID_RESTORE_PAGE);                                          
1266         }                                                                                                
1267     }                                                                                                    
1268                                                                                                          
1269     // If there is already a loader task running, tell it to stop.                                       
1270     // returns true if isLaunching() was true on the old task                                            
1271     private boolean stopLoaderLocked() {                                                                 
1272         boolean isLaunching = false;                                                                     
1273         LoaderTask oldTask = mLoaderTask;                                                                
1274         if (oldTask != null) {                                                                           
1275             if (oldTask.isLaunching()) {                                                                 
1276                 isLaunching = true;                                                                      
1277             }                                                                                            
1278             oldTask.stopLocked();                                                                        
1279         }                                                                                                
1280         return isLaunching;                                                                              
1281     }                                                                                                    
1282                                                                                                          
1283     public boolean isCurrentCallbacks(Callbacks callbacks) {                                             
1284         return (mCallbacks != null && mCallbacks.get() == callbacks);                                    
1285     }                                                                                                    
1286                                                                                                          
1287     public void startLoader(boolean isLaunching, int synchronousBindPage) {                              
1288         startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);                                 
1289     }                                                                                                    
1290                                                                                                          
1291     public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {               
1292         synchronized(mLock) {                                                                            
1293             if (DEBUG_LOADERS) {                                                                         
1294                 Log.d(TAG, "startLoader isLaunching=" + isLaunching);                                    
1295             }                                                                                            
1296             // Clear any deferred bind-runnables from the synchronized load process                      
1297             // We must do this before any loading/binding is scheduled below.                            
1298             synchronized(mDeferredBindRunnables) {                                                       
1299                 mDeferredBindRunnables.clear();                                                          
1300             }                                                                                            
1301             // Don't bother to start the thread if we know it's not going to do anything                 
1302             if ((mCallbacks != null) && (mCallbacks.get() != null)) {                                    
1303                 // If there is already one running, tell it to stop.                                     
1304                 // also, don't downgrade isLaunching if we're already running                            
1305                 isLaunching = isLaunching || stopLoaderLocked();                                         
1306                 mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);                 
1307                 if (((synchronousBindPage != PagedView.INVALID_RESTORE_PAGE) && mAllAppsLoaded) && mWorks🔵
1308                     mLoaderTask.runBindSynchronousPage(synchronousBindPage);                             
1309                 } else {                                                                                 
1310                     sWorkerThread.setPriority(Thread.NORM_PRIORITY);                                     
1311                     sWorker.post(mLoaderTask);                                                           
1312                 }                                                                                        
1313             }                                                                                            
1314         }                                                                                                
1315     }                                                                                                    
1316                                                                                                          
1317     void bindRemainingSynchronousPages() {                                                               
1318         // Post the remaining side pages to be loaded                                                    
1319         if (!mDeferredBindRunnables.isEmpty()) {                                                         
1320             Runnable[] deferredBindRunnables = null;                                                     
1321             synchronized(mDeferredBindRunnables) {                                                       
1322                 deferredBindRunnables = mDeferredBindRunnables.toArray(new Runnable[mDeferredBindRunnable🔵
1323                 mDeferredBindRunnables.clear();                                                          
1324             }                                                                                            
1325             for (final Runnable r : deferredBindRunnables) {                                             
1326                 mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);                                          
1327             }                                                                                            
1328         }                                                                                                
1329     }                                                                                                    
1330                                                                                                          
1331     public void stopLoader() {                                                                           
1332         synchronized (mLock) {                                                                           
1333             if (mLoaderTask != null) {                                                                   
1334                 mLoaderTask.stopLocked();                                                                
1335             }                                                                                            
1336         }                                                                                                
1337     }                                                                                                    
1338                                                                                                          
1339     /** Loads the workspace screens db into a map of Rank -> ScreenId */                                 
1340     private static TreeMap<Integer, Long> loadWorkspaceScreensDb(Context context) {                      
1341         final ContentResolver contentResolver = context.getContentResolver();                            
1342         final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                            
1343         final Cursor sc = contentResolver.query(screensUri, null, null, null, null);                     
1344         TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();                            
1345         try {                                                                                            
1346             final int idIndex = sc.getColumnIndexOrThrow(LauncherSettings.WorkspaceScreens._ID);         
1347             final int rankIndex = sc.getColumnIndexOrThrow(LauncherSettings.WorkspaceScreens.SCREEN_RANK)🔵
1348             while (sc.moveToNext()) {                                                                    
1349                 try {                                                                                    
1350                     long screenId = sc.getLong(idIndex);                                                 
1351                     int rank = sc.getInt(rankIndex);                                                     
1352                     orderedScreens.put(rank, screenId);                                                  
1353                 } catch (java.lang.Exception e) {                                                        
1354                     Launcher.addDumpLog(TAG, "Desktop items loading interrupted - invalid screens: " + e,🔵
1355                 }                                                                                        
1356             }                                                                                            
1357         } finally {                                                                                      
1358             sc.close();                                                                                  
1359         }                                                                                                
1360         // Log to disk                                                                                   
1361         Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);                           
1362         ArrayList<String> orderedScreensPairs = new ArrayList<String>();                                 
1363         for (Integer i : orderedScreens.keySet()) {                                                      
1364             orderedScreensPairs.add(((("{ " + i) + ": ") + orderedScreens.get(i)) + " }");               
1365         }                                                                                                
1366         Launcher.addDumpLog(TAG, "11683562 -   screens: " + TextUtils.join(", ", orderedScreensPairs), tr🔵
1367         return orderedScreens;                                                                           
1368     }                                                                                                    
1369                                                                                                          
1370     public boolean isAllAppsLoaded() {                                                                   
1371         return mAllAppsLoaded;                                                                           
1372     }                                                                                                    
1373                                                                                                          
1374     boolean isLoadingWorkspace() {                                                                       
1375         synchronized (mLock) {                                                                           
1376             if (mLoaderTask != null) {                                                                   
1377                 return mLoaderTask.isLoadingWorkspace();                                                 
1378             }                                                                                            
1379         }                                                                                                
1380         return false;                                                                                    
1381     }                                                                                                    
1382                                                                                                          
1383     /**                                                                                                  
1384      * Runnable for the thread that loads the contents of the launcher:                                  
1385      *   - workspace icons                                                                               
1386      *   - widgets                                                                                       
1387      *   - all apps icons                                                                                
1388      */                                                                                                  
1389     private class LoaderTask implements Runnable {                                                       
1390         private Context mContext;                                                                        
1391                                                                                                          
1392         private boolean mIsLaunching;                                                                    
1393                                                                                                          
1394         private boolean mIsLoadingAndBindingWorkspace;                                                   
1395                                                                                                          
1396         private boolean mStopped;                                                                        
1397                                                                                                          
1398         private boolean mLoadAndBindStepFinished;                                                        
1399                                                                                                          
1400         private int mFlags;                                                                              
1401                                                                                                          
1402         private HashMap<Object, CharSequence> mLabelCache;                                               
1403                                                                                                          
1404         LoaderTask(Context context, boolean isLaunching, int flags) {                                    
1405             mContext = context;                                                                          
1406             mIsLaunching = isLaunching;                                                                  
1407             mLabelCache = new HashMap<Object, CharSequence>();                                           
1408             mFlags = flags;                                                                              
1409         }                                                                                                
1410                                                                                                          
1411         boolean isLaunching() {                                                                          
1412             return mIsLaunching;                                                                         
1413         }                                                                                                
1414                                                                                                          
1415         boolean isLoadingWorkspace() {                                                                   
1416             return mIsLoadingAndBindingWorkspace;                                                        
1417         }                                                                                                
1418                                                                                                          
1419         /** Returns whether this is an upgrade path */                                                   
1420         private boolean loadAndBindWorkspace() {                                                         
1421             mIsLoadingAndBindingWorkspace = true;                                                        
1422                                                                                                          
1423             // Load the workspace                                                                        
1424             if (DEBUG_LOADERS) {                                                                         
1425                 Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);                 
1426             }                                                                                            
1427                                                                                                          
1428             boolean isUpgradePath = false;                                                               
1429             if (!mWorkspaceLoaded) {                                                                     
1430                 isUpgradePath = loadWorkspace();                                                         
1431                 synchronized (LoaderTask.this) {                                                         
1432                     if (mStopped) {                                                                      
1433                         return isUpgradePath;                                                            
1434                     }                                                                                    
1435                     mWorkspaceLoaded = true;                                                             
1436                 }                                                                                        
1437             }                                                                                            
1438                                                                                                          
1439             // Bind the workspace                                                                        
1440             bindWorkspace(-1, isUpgradePath);                                                            
1441             return isUpgradePath;                                                                        
1442         }                                                                                                
1443                                                                                                          
1444         private void waitForIdle() {                                                                     
1445             // Wait until the either we're stopped or the other threads are done.                        
1446             // This way we don't start loading all apps until the workspace has settled                  
1447             // down.                                                                                     
1448             synchronized (LoaderTask.this) {                                                             
1449                 final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;           
1450                                                                                                          
1451                 mHandler.postIdle(new Runnable() {                                                       
1452                         public void run() {                                                              
1453                             synchronized (LoaderTask.this) {                                             
1454                                 mLoadAndBindStepFinished = true;                                         
1455                                 if (DEBUG_LOADERS) {                                                     
1456                                     Log.d(TAG, "done with previous binding step");                       
1457                                 }                                                                        
1458                                 LoaderTask.this.notify();                                                
1459                             }                                                                            
1460                         }                                                                                
1461                     });                                                                                  
1462                                                                                                          
1463                 while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) {               
1464                     try {                                                                                
1465                         // Just in case mFlushingWorkerThread changes but we aren't woken up,            
1466                         // wait no longer than 1sec at a time                                            
1467                         this.wait(1000);                                                                 
1468                     } catch (InterruptedException ex) {                                                  
1469                         // Ignore                                                                        
1470                     }                                                                                    
1471                 }                                                                                        
1472                 if (DEBUG_LOADERS) {                                                                     
1473                     Log.d(TAG, "waited "                                                                 
1474                             + (SystemClock.uptimeMillis()-workspaceWaitTime)                             
1475                             + "ms for previous step to finish binding");                                 
1476                 }                                                                                        
1477             }                                                                                            
1478         }                                                                                                
1479                                                                                                          
1480         void runBindSynchronousPage(int synchronousBindPage) {                                           
1481             if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {                                 
1482                 // Ensure that we have a valid page index to load synchronously                          
1483                 throw new RuntimeException("Should not call runBindSynchronousPage() without " +         
1484                         "valid page index");                                                             
1485             }                                                                                            
1486             if (!mAllAppsLoaded || !mWorkspaceLoaded) {                                                  
1487                 // Ensure that we don't try and bind a specified page when the pages have not been       
1488                 // loaded already (we should load everything asynchronously in that case)                
1489                 throw new RuntimeException("Expecting AllApps and Workspace to be loaded");              
1490             }                                                                                            
1491             synchronized (mLock) {                                                                       
1492                 if (mIsLoaderTaskRunning) {                                                              
1493                     // Ensure that we are never running the background loading at this point since       
1494                     // we also touch the background collections                                          
1495                     throw new RuntimeException("Error! Background loading is already running");          
1496                 }                                                                                        
1497             }                                                                                            
1498                                                                                                          
1499             // XXX: Throw an exception if we are already loading (since we touch the worker thread       
1500             //      data structures, we can't allow any other thread to touch that data, but because     
1501             //      this call is synchronous, we can get away with not locking).                         
1502                                                                                                          
1503             // The LauncherModel is static in the LauncherAppState and mHandler may have queued          
1504             // operations from the previous activity.  We need to ensure that all queued operations      
1505             // are executed before any synchronous binding work is done.                                 
1506             mHandler.flush();                                                                            
1507                                                                                                          
1508             // Divide the set of loaded items into those that we are binding synchronously, and          
1509             // everything else that is to be bound normally (asynchronously).                            
1510             bindWorkspace(synchronousBindPage, false);                                                   
1511             // XXX: For now, continue posting the binding of AllApps as there are other issues that      
1512             //      arise from that.                                                                     
1513             onlyBindAllApps();                                                                           
1514         }                                                                                                
1515                                                                                                          
1516         public void run() {                                                                              
1517             boolean isUpgrade = false;                                                                   
1518             synchronized(mLock) {                                                                        
1519                 mIsLoaderTaskRunning = true;                                                             
1520             }                                                                                            
1521             // Optimize for end-user experience: if the Launcher is up and // running with the           
1522             // All Apps interface in the foreground, load All Apps first. Otherwise, load the            
1523             // workspace first (default).                                                                
1524             keep_running : {                                                                             
1525                 // Elevate priority when Home launches for the first time to avoid                       
1526                 // starving at boot time. Staring at a blank home is not cool.                           
1527                 synchronized(mLock) {                                                                    
1528                     if (DEBUG_LOADERS) {                                                                 
1529                         Log.d(TAG, "Setting thread priority to " + (mIsLaunching ? "DEFAULT" : "BACKGROUN🔵
1530                     }                                                                                    
1531                     Process.setThreadPriority(mIsLaunching ? java.lang.Process.THREAD_PRIORITY_DEFAULT : 🔵
1532                 }                                                                                        
1533                 if (DEBUG_LOADERS) {                                                                     
1534                     Log.d(TAG, "step 1: loading workspace");                                             
1535                 }                                                                                        
1536                 isUpgrade = loadAndBindWorkspace();                                                      
1537                 if (mStopped) {                                                                          
1538                     break keep_running;                                                                  
1539                 }                                                                                        
1540                 // Whew! Hard work done.  Slow us down, and wait until the UI thread has                 
1541                 // settled down.                                                                         
1542                 synchronized(mLock) {                                                                    
1543                     if (mIsLaunching) {                                                                  
1544                         if (DEBUG_LOADERS) {                                                             
1545                             Log.d(TAG, "Setting thread priority to BACKGROUND");                         
1546                         }                                                                                
1547                         Process.setThreadPriority(java.lang.Process.THREAD_PRIORITY_BACKGROUND);         
1548                     }                                                                                    
1549                 }                                                                                        
1550                 waitForIdle();                                                                           
1551                 // second step                                                                           
1552                 if (DEBUG_LOADERS) {                                                                     
1553                     Log.d(TAG, "step 2: loading all apps");                                              
1554                 }                                                                                        
1555                 loadAndBindAllApps();                                                                    
1556                 // Restore the default thread priority after we are done loading items                   
1557                 synchronized(mLock) {                                                                    
1558                     Process.setThreadPriority(java.lang.Process.THREAD_PRIORITY_DEFAULT);                
1559                 }                                                                                        
1560             }                                                                                            
1561             // Update the saved icons if necessary                                                       
1562             if (DEBUG_LOADERS) {                                                                         
1563                 Log.d(TAG, "Comparing loaded icons to database icons");                                  
1564             }                                                                                            
1565             synchronized(sBgLock) {                                                                      
1566                 for (Object key : sBgDbIconCache.keySet()) {                                             
1567                     updateSavedIcon(mContext, ((ShortcutInfo) (key)), sBgDbIconCache.get(key));          
1568                 }                                                                                        
1569                 sBgDbIconCache.clear();                                                                  
1570             }                                                                                            
1571             if (LauncherAppState.isDisableAllApps()) {                                                   
1572                 // Ensure that all the applications that are in the system are                           
1573                 // represented on the home screen.                                                       
1574                 if ((!UPGRADE_USE_MORE_APPS_FOLDER) || (!isUpgrade)) {                                   
1575                     verifyApplications();                                                                
1576                 }                                                                                        
1577             }                                                                                            
1578             // Clear out this reference, otherwise we end up holding it until all of the                 
1579             // callback runnables are done.                                                              
1580             mContext = null;                                                                             
1581             synchronized(mLock) {                                                                        
1582                 // If we are still the last one to be scheduled, remove ourselves.                       
1583                 if (mLoaderTask == this) {                                                               
1584                     mLoaderTask = null;                                                                  
1585                 }                                                                                        
1586                 mIsLoaderTaskRunning = false;                                                            
1587             }                                                                                            
1588         }                                                                                                
1589                                                                                                          
1590         public void stopLocked() {                                                                       
1591             synchronized (LoaderTask.this) {                                                             
1592                 mStopped = true;                                                                         
1593                 this.notify();                                                                           
1594             }                                                                                            
1595         }                                                                                                
1596                                                                                                          
1597         /**                                                                                              
1598          * Gets the callbacks object.  If we've been stopped, or if the launcher object                  
1599          * has somehow been garbage collected, return null instead.  Pass in the Callbacks               
1600          * object that was around when the deferred message was scheduled, and if there's                
1601          * a new Callbacks object around then also return null.  This will save us from                  
1602          * calling onto it with data that will be ignored.                                               
1603          */                                                                                              
1604         Callbacks tryGetCallbacks(Callbacks oldCallbacks) {                                              
1605             synchronized (mLock) {                                                                       
1606                 if (mStopped) {                                                                          
1607                     return null;                                                                         
1608                 }                                                                                        
1609                                                                                                          
1610                 if (mCallbacks == null) {                                                                
1611                     return null;                                                                         
1612                 }                                                                                        
1613                                                                                                          
1614                 final Callbacks callbacks = mCallbacks.get();                                            
1615                 if (callbacks != oldCallbacks) {                                                         
1616                     return null;                                                                         
1617                 }                                                                                        
1618                 if (callbacks == null) {                                                                 
1619                     Log.w(TAG, "no mCallbacks");                                                         
1620                     return null;                                                                         
1621                 }                                                                                        
1622                                                                                                          
1623                 return callbacks;                                                                        
1624             }                                                                                            
1625         }                                                                                                
1626                                                                                                          
1627         private void verifyApplications() {                                                              
1628             final Context context = mApp.getContext();                                                   
1629             // Cross reference all the applications in our apps list with items in the workspace         
1630             ArrayList<ItemInfo> tmpInfos;                                                                
1631             ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();                                       
1632             synchronized(sBgLock) {                                                                      
1633                 for (AppInfo app : mBgAllAppsList.data) {                                                
1634                     tmpInfos = getItemInfoForComponentName(app.componentName, app.user);                 
1635                     if (tmpInfos.isEmpty()) {                                                            
1636                         // We are missing an application icon, so add this to the workspace              
1637                         added.add(app);                                                                  
1638                         // This is a rare event, so lets log it                                          
1639                         Log.e(TAG, "Missing Application on load: " + app);                               
1640                     }                                                                                    
1641                 }                                                                                        
1642             }                                                                                            
1643             if (!added.isEmpty()) {                                                                      
1644                 addAndBindAddedWorkspaceApps(context, added);                                            
1645             }                                                                                            
1646         }                                                                                                
1647                                                                                                          
1648         // check & update map of what's occupied; used to discard overlapping/invalid items              
1649         private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item, AtomicBoo🔵
1650             LauncherAppState app = LauncherAppState.getInstance();                                       
1651             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
1652             final int countX = ((int) (grid.numColumns));                                                
1653             final int countY = ((int) (grid.numRows));                                                   
1654             long containerIndex = item.screenId;                                                         
1655             if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                        
1656                 // Return early if we detect that an item is under the hotseat button                    
1657                 if ((mCallbacks == null) || mCallbacks.get().isAllAppsButtonRank(((int) (item.screenId)))🔵
1658                     deleteOnInvalidPlacement.set(true);                                                  
1659                     Log.e(TAG, ((((((("Error loading shortcut into hotseat " + item) + " into position ("🔵
1660                     return false;                                                                        
1661                 }                                                                                        
1662                 final ItemInfo[][] hotseatItems = occupied.get(((long) (LauncherSettings.Favorites.CONTAI🔵
1663                 if (item.screenId >= grid.numHotseatIcons) {                                             
1664                     Log.e(TAG, ((((("Error loading shortcut " + item) + " into hotseat position ") + item🔵
1665                     return false;                                                                        
1666                 }                                                                                        
1667                 if (hotseatItems != null) {                                                              
1668                     if (hotseatItems[((int) (item.screenId))][0] != null) {                              
1669                         Log.e(TAG, (((((((("Error loading shortcut into hotseat " + item) + " into positi🔵
1670                         return false;                                                                    
1671                     } else {                                                                             
1672                         hotseatItems[((int) (item.screenId))][0] = item;                                 
1673                         return true;                                                                     
1674                     }                                                                                    
1675                 } else {                                                                                 
1676                     final ItemInfo[][] items = new ItemInfo[((int) (grid.numHotseatIcons))][1];          
1677                     items[((int) (item.screenId))][0] = item;                                            
1678                     occupied.put(((long) (LauncherSettings.Favorites.CONTAINER_HOTSEAT)), items);        
1679                     return true;                                                                         
1680                 }                                                                                        
1681             } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {                 
1682                 // Skip further checking if it is not the hotseat or workspace container                 
1683                 return true;                                                                             
1684             }                                                                                            
1685             if (!occupied.containsKey(item.screenId)) {                                                  
1686                 ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];                               
1687                 occupied.put(item.screenId, items);                                                      
1688             }                                                                                            
1689             final ItemInfo[][] screens = occupied.get(item.screenId);                                    
1690             if (((((item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) && (item.cellX < 0)) 🔵
1691                 Log.e(TAG, ((((((((((((("Error loading shortcut " + item) + " into cell (") + containerIn🔵
1692                 return false;                                                                            
1693             }                                                                                            
1694             // Check if any workspace icons overlap with each other                                      
1695             for (int x = item.cellX; x < (item.cellX + item.spanX); x++) {                               
1696                 for (int y = item.cellY; y < (item.cellY + item.spanY); y++) {                           
1697                     if (screens[x][y] != null) {                                                         
1698                         Log.e(TAG, (((((((((("Error loading shortcut " + item) + " into cell (") + contai🔵
1699                         return false;                                                                    
1700                     }                                                                                    
1701                 }                                                                                        
1702             }                                                                                            
1703             for (int x = item.cellX; x < (item.cellX + item.spanX); x++) {                               
1704                 for (int y = item.cellY; y < (item.cellY + item.spanY); y++) {                           
1705                     screens[x][y] = item;                                                                
1706                 }                                                                                        
1707             }                                                                                            
1708             return true;                                                                                 
1709         }                                                                                                
1710                                                                                                          
1711         /** Clears all the sBg data structures */                                                        
1712         private void clearSBgDataStructures() {                                                          
1713             synchronized (sBgLock) {                                                                     
1714                 sBgWorkspaceItems.clear();                                                               
1715                 sBgAppWidgets.clear();                                                                   
1716                 sBgFolders.clear();                                                                      
1717                 sBgItemsIdMap.clear();                                                                   
1718                 sBgDbIconCache.clear();                                                                  
1719                 sBgWorkspaceScreens.clear();                                                             
1720             }                                                                                            
1721         }                                                                                                
1722                                                                                                          
1723         /** Returns whether this is an upgrade path */                                                   
1724         private boolean loadWorkspace() {                                                                
1725             // Log to disk                                                                               
1726             Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);                                
1727             final long t = (DEBUG_LOADERS) ? SystemClock.uptimeMillis() : 0;                             
1728             final Context context = mContext;                                                            
1729             final ContentResolver contentResolver = context.getContentResolver();                        
1730             final PackageManager manager = context.getPackageManager();                                  
1731             final AppWidgetManager widgets = AppWidgetManager.getInstance(context);                      
1732             final boolean isSafeMode = manager.isSafeMode();                                             
1733             final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);             
1734             final boolean isSdCardReady = context.registerReceiver(null, new IntentFilter(StartupReceiver🔵
1735             LauncherAppState app = LauncherAppState.getInstance();                                       
1736             DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                
1737             int countX = ((int) (grid.numColumns));                                                      
1738             int countY = ((int) (grid.numRows));                                                         
1739             if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {                                           
1740                 Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);            
1741                 LauncherAppState.getLauncherProvider().deleteDatabase();                                 
1742             }                                                                                            
1743             if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {                                         
1744                 // append the user's Launcher2 shortcuts                                                 
1745                 Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);               
1746                 LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();                      
1747             } else {                                                                                     
1748                 // Make sure the default workspace is loaded                                             
1749                 Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);             
1750                 LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();                
1751             }                                                                                            
1752             // This code path is for our old migration code and should no longer be exercised            
1753             boolean loadedOldDb = false;                                                                 
1754             // Log to disk                                                                               
1755             Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);                  
1756             synchronized(sBgLock) {                                                                      
1757                 clearSBgDataStructures();                                                                
1758                 final HashSet<String> installingPkgs = PackageInstallerCompat.getInstance(mContext).updat🔵
1759                 final ArrayList<Long> itemsToRemove = new ArrayList<Long>();                             
1760                 final ArrayList<Long> restoredRows = new ArrayList<Long>();                              
1761                 final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;           
1762                 if (DEBUG_LOADERS) {                                                                     
1763                     Log.d(TAG, "loading model from " + contentUri);                                      
1764                 }                                                                                        
1765                 final Cursor c = contentResolver.query(contentUri, null, null, null, null);              
1766                 // +1 for the hotseat (it can be larger than the workspace)                              
1767                 // Load workspace in reverse order to ensure that latest items are loaded first (and     
1768                 // before any earlier duplicates)                                                        
1769                 final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();          
1770                 try {                                                                                    
1771                     final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);         
1772                     final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);  
1773                     final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);    
1774                     final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYP🔵
1775                     final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);      
1776                     final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_🔵
1777                     final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON🔵
1778                     final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAIN🔵
1779                     final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYP🔵
1780                     final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWI🔵
1781                     final int appWidgetProviderIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites🔵
1782                     final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);  
1783                     final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);    
1784                     final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);    
1785                     final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);    
1786                     final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);    
1787                     final int restoredIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.RESTORED🔵
1788                     final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE🔵
1789                     //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);      
1790                     //final int displayModeIndex = c.getColumnIndexOrThrow(                              
1791                     //        LauncherSettings.Favorites.DISPLAY_MODE);                                  
1792                     ShortcutInfo info;                                                                   
1793                     String intentDescription;                                                            
1794                     LauncherAppWidgetInfo appWidgetInfo;                                                 
1795                     int container;                                                                       
1796                     long id;                                                                             
1797                     Intent intent;                                                                       
1798                     UserHandleCompat user;                                                               
1799                     while ((!mStopped) && c.moveToNext()) {                                              
1800                         AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);               
1801                         try {                                                                            
1802                             int itemType = c.getInt(itemTypeIndex);                                      
1803                             boolean restored = 0 != c.getInt(restoredIndex);                             
1804                             boolean allowMissingTarget = false;                                          
1805                             switch (itemType) {                                                          
1806                                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION :                  
1807                                 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT :                     
1808                                     id = c.getLong(idIndex);                                             
1809                                     intentDescription = c.getString(intentIndex);                        
1810                                     long serialNumber = c.getInt(profileIdIndex);                        
1811                                     user = mUserManager.getUserForSerialNumber(serialNumber);            
1812                                     int promiseType = c.getInt(restoredIndex);                           
1813                                     if (user == null) {                                                  
1814                                         // User has been deleted remove the item.                        
1815                                         itemsToRemove.add(id);                                           
1816                                         continue;                                                        
1817                                     }                                                                    
1818                                     try {                                                                
1819                                         intent = Intent.parseUri(intentDescription, 0);                  
1820                                         ComponentName cn = intent.getComponent();                        
1821                                         if ((cn != null) && (cn.getPackageName() != null)) {             
1822                                             boolean validPkg = launcherApps.isPackageEnabledForProfile(cn🔵
1823                                             boolean validComponent = validPkg && launcherApps.isActivityE🔵
1824                                             if (validComponent) {                                        
1825                                                 if (restored) {                                          
1826                                                     // no special handling necessary for this item       
1827                                                     restoredRows.add(id);                                
1828                                                     restored = false;                                    
1829                                                 }                                                        
1830                                             } else if (validPkg) {                                       
1831                                                 intent = null;                                           
1832                                                 if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 🔵
1833                                                     // We allow auto install apps to have their intent   
1834                                                     // updated after an install.                         
1835                                                     intent = manager.getLaunchIntentForPackage(cn.getPack🔵
1836                                                     if (intent != null) {                                
1837                                                         ContentValues values = new ContentValues();      
1838                                                         values.put(LauncherSettings.Favorites.INTENT, int🔵
1839                                                         String where = BaseColumns._ID + "= ?";          
1840                                                         String[] args = new java.lang.String[]{ Long.toSt🔵
1841                                                         contentResolver.update(contentUri, values, where,🔵
1842                                                     }                                                    
1843                                                 }                                                        
1844                                                 if (intent == null) {                                    
1845                                                     // The app is installed but the component is no      
1846                                                 // longer available.                                     
1847                                                     Launcher.addDumpLog(TAG, "Invalid component removed: 🔵
1848                                                     itemsToRemove.add(id);                               
1849                                                     continue;                                            
1850                                                 } else {                                                 
1851                                                     // no special handling necessary for this item       
1852                                                     restoredRows.add(id);                                
1853                                                     restored = false;                                    
1854                                                 }                                                        
1855                                             } else if (restored) {                                       
1856                                             // Package is not yet available but might be                 
1857                                             // installed later.                                          
1858                                                 Launcher.addDumpLog(TAG, "package not yet restored: " + c🔵
1859                                                 if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 🔵
1860                                                     // Restore has started once.                         
1861                                                 } else if (installingPkgs.contains(cn.getPackageName())) 🔵
1862                                                     // App restore has started. Update the flag          
1863                                                     promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;    
1864                                                     ContentValues values = new ContentValues();          
1865                                                     values.put(LauncherSettings.Favorites.RESTORED, promi🔵
1866                                                     String where = BaseColumns._ID + "= ?";              
1867                                                     String[] args = new java.lang.String[]{ Long.toString🔵
1868                                                     contentResolver.update(contentUri, values, where, arg🔵
1869                                                 } else if (REMOVE_UNRESTORED_ICONS) {                    
1870                                                     Launcher.addDumpLog(TAG, "Unrestored package removed:🔵
1871                                                     itemsToRemove.add(id);                               
1872                                                     continue;                                            
1873                                                 }                                                        
1874                                             } else if (isSdCardReady) {                                  
1875                                             // Do not wait for external media load anymore.              
1876                                                 // Log the invalid package, and remove it                
1877                                                 Launcher.addDumpLog(TAG, "Invalid package removed: " + cn🔵
1878                                                 itemsToRemove.add(id);                                   
1879                                                 continue;                                                
1880                                             } else {                                                     
1881                                                 // SdCard is not ready yet. Package might get available, 
1882                                                 // once it is ready.                                     
1883                                                 Launcher.addDumpLog(TAG, ("Invalid package: " + cn) + " (🔵
1884                                                 HashSet<String> pkgs = sPendingPackages.get(user);       
1885                                                 if (pkgs == null) {                                      
1886                                                     pkgs = new HashSet<String>();                        
1887                                                     sPendingPackages.put(user, pkgs);                    
1888                                                 }                                                        
1889                                                 pkgs.add(cn.getPackageName());                           
1890                                                 allowMissingTarget = true;                               
1891                                             // Add the icon on the workspace anyway.                     
1892                                             }                                                            
1893                                         } else if (cn == null) {                                         
1894                                             // For shortcuts with no component, keep them as they are    
1895                                             restoredRows.add(id);                                        
1896                                             restored = false;                                            
1897                                         }                                                                
1898                                     } catch (URISyntaxException e) {                                     
1899                                         Launcher.addDumpLog(TAG, "Invalid uri: " + intentDescription, tru🔵
1900                                         continue;                                                        
1901                                     }                                                                    
1902                                     if (restored) {                                                      
1903                                         if (user.equals(UserHandleCompat.myUserHandle())) {              
1904                                             Launcher.addDumpLog(TAG, "constructing info for partially res🔵
1905                                             info = getRestoredItemInfo(c, titleIndex, intent, promiseType🔵
1906                                             intent = getRestoredItemIntent(c, context, intent);          
1907                                         } else {                                                         
1908                                             // Don't restore items for other profiles.                   
1909                                             itemsToRemove.add(id);                                       
1910                                             continue;                                                    
1911                                         }                                                                
1912                                     } else if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATI🔵
1913                                         info = getShortcutInfo(manager, intent, user, context, c, iconInd🔵
1914                                     } else {                                                             
1915                                         info = getShortcutInfo(c, context, iconTypeIndex, iconPackageInde🔵
1916                                     // App shortcuts that used to be automatically added to Launcher     
1917                                     // didn't always have the correct intent flags set, so do that       
1918                                     // here                                                              
1919                                         if ((((intent.getAction() != null) && (intent.getCategories() != 🔵
1920                                             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_A🔵
1921                                         }                                                                
1922                                     }                                                                    
1923                                     if (info != null) {                                                  
1924                                         info.id = id;                                                    
1925                                         info.intent = intent;                                            
1926                                         container = c.getInt(containerIndex);                            
1927                                         info.container = container;                                      
1928                                         info.screenId = c.getInt(screenIndex);                           
1929                                         info.cellX = c.getInt(cellXIndex);                               
1930                                         info.cellY = c.getInt(cellYIndex);                               
1931                                         info.spanX = 1;                                                  
1932                                         info.spanY = 1;                                                  
1933                                         info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);      
1934                                         info.isDisabled = isSafeMode && (!Utilities.isSystemApp(context, 🔵
1935                                         // check & update map of what's occupied                         
1936                                         deleteOnInvalidPlacement.set(false);                             
1937                                         if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)🔵
1938                                             if (deleteOnInvalidPlacement.get()) {                        
1939                                                 itemsToRemove.add(id);                                   
1940                                             }                                                            
1941                                             break;                                                       
1942                                         }                                                                
1943                                         switch (container) {                                             
1944                                             case LauncherSettings.Favorites.CONTAINER_DESKTOP :          
1945                                             case LauncherSettings.Favorites.CONTAINER_HOTSEAT :          
1946                                                 sBgWorkspaceItems.add(info);                             
1947                                                 break;                                                   
1948                                             default :                                                    
1949                                         // Item is in a user folder                                      
1950                                                 FolderInfo folderInfo = findOrMakeFolder(sBgFolders, cont🔵
1951                                                 folderInfo.add(info);                                    
1952                                                 break;                                                   
1953                                         }                                                                
1954                                         sBgItemsIdMap.put(info.id, info);                                
1955                                         // now that we've loaded everthing re-save it with the           
1956                                         // icon in case it disappears somehow.                           
1957                                         queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);        
1958                                     } else {                                                             
1959                                         throw new RuntimeException("Unexpected null ShortcutInfo");      
1960                                     }                                                                    
1961                                     break;                                                               
1962                                 case LauncherSettings.Favorites.ITEM_TYPE_FOLDER :                       
1963                                     id = c.getLong(idIndex);                                             
1964                                     FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);            
1965                                     folderInfo.title = c.getString(titleIndex);                          
1966                                     folderInfo.id = id;                                                  
1967                                     container = c.getInt(containerIndex);                                
1968                                     folderInfo.container = container;                                    
1969                                     folderInfo.screenId = c.getInt(screenIndex);                         
1970                                     folderInfo.cellX = c.getInt(cellXIndex);                             
1971                                     folderInfo.cellY = c.getInt(cellYIndex);                             
1972                                     folderInfo.spanX = 1;                                                
1973                                     folderInfo.spanY = 1;                                                
1974                                     // check & update map of what's occupied                             
1975                                     deleteOnInvalidPlacement.set(false);                                 
1976                                     if (!checkItemPlacement(occupied, folderInfo, deleteOnInvalidPlacemen🔵
1977                                         if (deleteOnInvalidPlacement.get()) {                            
1978                                             itemsToRemove.add(id);                                       
1979                                         }                                                                
1980                                         break;                                                           
1981                                     }                                                                    
1982                                     switch (container) {                                                 
1983                                         case LauncherSettings.Favorites.CONTAINER_DESKTOP :              
1984                                         case LauncherSettings.Favorites.CONTAINER_HOTSEAT :              
1985                                             sBgWorkspaceItems.add(folderInfo);                           
1986                                             break;                                                       
1987                                     }                                                                    
1988                                     if (restored) {                                                      
1989                                         // no special handling required for restored folders             
1990                                         restoredRows.add(id);                                            
1991                                     }                                                                    
1992                                     sBgItemsIdMap.put(folderInfo.id, folderInfo);                        
1993                                     sBgFolders.put(folderInfo.id, folderInfo);                           
1994                                     break;                                                               
1995                                 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET :                    
1996                                     // Read all Launcher-specific widget details                         
1997                                     int appWidgetId = c.getInt(appWidgetIdIndex);                        
1998                                     String savedProvider = c.getString(appWidgetProviderIndex);          
1999                                     id = c.getLong(idIndex);                                             
2000                                     final ComponentName component = ComponentName.unflattenFromString(sav🔵
2001                                     final int restoreStatus = c.getInt(restoredIndex);                   
2002                                     final boolean isIdValid = (restoreStatus & LauncherAppWidgetInfo.FLAG🔵
2003                                     final boolean wasProviderReady = (restoreStatus & LauncherAppWidgetIn🔵
2004                                     final AppWidgetProviderInfo provider = (isIdValid) ? widgets.getAppWi🔵
2005                                     final boolean isProviderReady = isValidProvider(provider);           
2006                                     if (((!isSafeMode) && wasProviderReady) && (!isProviderReady)) {     
2007                                         String log = ((("Deleting widget that isn\'t installed anymore: "🔵
2008                                         Log.e(TAG, log);                                                 
2009                                         Launcher.addDumpLog(TAG, log, false);                            
2010                                         itemsToRemove.add(id);                                           
2011                                     } else {                                                             
2012                                         if (isProviderReady) {                                           
2013                                             appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, provid🔵
2014                                             int[] minSpan = Launcher.getMinSpanForWidget(context, provide🔵
2015                                             appWidgetInfo.minSpanX = minSpan[0];                         
2016                                             appWidgetInfo.minSpanY = minSpan[1];                         
2017                                             int status = restoreStatus;                                  
2018                                             if (!wasProviderReady) {                                     
2019                                                 // If provider was not previously ready, update the      
2020                                                 // status and UI flag.                                   
2021                                                 // Id would be valid only if the widget restore broadcast🔵
2022                                                 if (isIdValid) {                                         
2023                                                     status = LauncherAppWidgetInfo.RESTORE_COMPLETED;    
2024                                                 } else {                                                 
2025                                                     status &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_RE🔵
2026                                                 }                                                        
2027                                             }                                                            
2028                                             appWidgetInfo.restoreStatus = status;                        
2029                                         } else {                                                         
2030                                             Log.v(TAG, (((("Widget restore pending id=" + id) + " appWidg🔵
2031                                             appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, compon🔵
2032                                             appWidgetInfo.restoreStatus = restoreStatus;                 
2033                                             if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_START🔵
2034                                                 // Restore has started once.                             
2035                                             } else if (installingPkgs.contains(component.getPackageName()🔵
2036                                                 // App restore has started. Update the flag              
2037                                                 appWidgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG🔵
2038                                             } else if (REMOVE_UNRESTORED_ICONS) {                        
2039                                                 Launcher.addDumpLog(TAG, "Unrestored widget removed: " + 🔵
2040                                                 itemsToRemove.add(id);                                   
2041                                                 continue;                                                
2042                                             }                                                            
2043                                         }                                                                
2044                                         appWidgetInfo.id = id;                                           
2045                                         appWidgetInfo.screenId = c.getInt(screenIndex);                  
2046                                         appWidgetInfo.cellX = c.getInt(cellXIndex);                      
2047                                         appWidgetInfo.cellY = c.getInt(cellYIndex);                      
2048                                         appWidgetInfo.spanX = c.getInt(spanXIndex);                      
2049                                         appWidgetInfo.spanY = c.getInt(spanYIndex);                      
2050                                         container = c.getInt(containerIndex);                            
2051                                         if ((container != LauncherSettings.Favorites.CONTAINER_DESKTOP) &🔵
2052                                             Log.e(TAG, "Widget found where container != " + "CONTAINER_DE🔵
2053                                             continue;                                                    
2054                                         }                                                                
2055                                         appWidgetInfo.container = c.getInt(containerIndex);              
2056                                         // check & update map of what's occupied                         
2057                                         deleteOnInvalidPlacement.set(false);                             
2058                                         if (!checkItemPlacement(occupied, appWidgetInfo, deleteOnInvalidP🔵
2059                                             if (deleteOnInvalidPlacement.get()) {                        
2060                                                 itemsToRemove.add(id);                                   
2061                                             }                                                            
2062                                             break;                                                       
2063                                         }                                                                
2064                                         String providerName = appWidgetInfo.providerName.flattenToString(🔵
2065                                         if ((!providerName.equals(savedProvider)) || (appWidgetInfo.resto🔵
2066                                             ContentValues values = new ContentValues();                  
2067                                             values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, pro🔵
2068                                             values.put(LauncherSettings.Favorites.RESTORED, appWidgetInfo🔵
2069                                             String where = BaseColumns._ID + "= ?";                      
2070                                             String[] args = new java.lang.String[]{ Long.toString(id) }; 
2071                                             contentResolver.update(contentUri, values, where, args);     
2072                                         }                                                                
2073                                         sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);              
2074                                         sBgAppWidgets.add(appWidgetInfo);                                
2075                                     }                                                                    
2076                                     break;                                                               
2077                             }                                                                            
2078                         } catch (java.lang.Exception e) {                                                
2079                             Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);      
2080                         }                                                                                
2081                     }                                                                                    
2082                 } finally {                                                                              
2083                     if (c != null) {                                                                     
2084                         c.close();                                                                       
2085                     }                                                                                    
2086                 }                                                                                        
2087                 // Break early if we've stopped loading                                                  
2088                 if (mStopped) {                                                                          
2089                     clearSBgDataStructures();                                                            
2090                     return false;                                                                        
2091                 }                                                                                        
2092                 if (itemsToRemove.size() > 0) {                                                          
2093                     ContentProviderClient client = contentResolver.acquireContentProviderClient(contentUr🔵
2094                     // Remove dead items                                                                 
2095                     for (long id : itemsToRemove) {                                                      
2096                         if (DEBUG_LOADERS) {                                                             
2097                             Log.d(TAG, "Removed id = " + id);                                            
2098                         }                                                                                
2099                         // Don't notify content observers                                                
2100                         try {                                                                            
2101                             client.delete(LauncherSettings.Favorites.getContentUri(id, false), null, null🔵
2102                         } catch (RemoteException e) {                                                    
2103                             Log.w(TAG, "Could not remove id = " + id);                                   
2104                         }                                                                                
2105                     }                                                                                    
2106                 }                                                                                        
2107                 if (restoredRows.size() > 0) {                                                           
2108                     ContentProviderClient updater = contentResolver.acquireContentProviderClient(contentU🔵
2109                     // Update restored items that no longer require special handling                     
2110                     try {                                                                                
2111                         StringBuilder selectionBuilder = new StringBuilder();                            
2112                         selectionBuilder.append(LauncherSettings.Favorites._ID);                         
2113                         selectionBuilder.append(" IN (");                                                
2114                         selectionBuilder.append(TextUtils.join(", ", restoredRows));                     
2115                         selectionBuilder.append(")");                                                    
2116                         ContentValues values = new ContentValues();                                      
2117                         values.put(LauncherSettings.Favorites.RESTORED, 0);                              
2118                         updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values, se🔵
2119                     } catch (RemoteException e) {                                                        
2120                         Log.w(TAG, "Could not update restored rows");                                    
2121                     }                                                                                    
2122                 }                                                                                        
2123                 if ((!isSdCardReady) && (!sPendingPackages.isEmpty())) {                                 
2124                     context.registerReceiver(new AppsAvailabilityCheck(), new IntentFilter(StartupReceive🔵
2125                 }                                                                                        
2126                 if (loadedOldDb) {                                                                       
2127                     long maxScreenId = 0;                                                                
2128                     // If we're importing we use the old screen order.                                   
2129                     for (ItemInfo item : sBgItemsIdMap.values()) {                                       
2130                         long screenId = item.screenId;                                                   
2131                         if ((item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) && (!sBgWork🔵
2132                             sBgWorkspaceScreens.add(screenId);                                           
2133                             if (screenId > maxScreenId) {                                                
2134                                 maxScreenId = screenId;                                                  
2135                             }                                                                            
2136                         }                                                                                
2137                     }                                                                                    
2138                     Collections.sort(sBgWorkspaceScreens);                                               
2139                     // Log to disk                                                                       
2140                     Launcher.addDumpLog(TAG, "11683562 -   maxScreenId: " + maxScreenId, true);          
2141                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " + TextUtils.join(", ", 🔵
2142                     LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);               
2143                     updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                            
2144                     // Update the max item id after we load an old db                                    
2145                     long maxItemId = 0;                                                                  
2146                     // If we're importing we use the old screen order.                                   
2147                     for (ItemInfo item : sBgItemsIdMap.values()) {                                       
2148                         maxItemId = Math.max(maxItemId, item.id);                                        
2149                     }                                                                                    
2150                     LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);                   
2151                 } else {                                                                                 
2152                     TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(mContext);            
2153                     for (Integer i : orderedScreens.keySet()) {                                          
2154                         sBgWorkspaceScreens.add(orderedScreens.get(i));                                  
2155                     }                                                                                    
2156                     // Log to disk                                                                       
2157                     Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " + TextUtils.join(", ", 🔵
2158                     // Remove any empty screens                                                          
2159                     ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);            
2160                     for (ItemInfo item : sBgItemsIdMap.values()) {                                       
2161                         long screenId = item.screenId;                                                   
2162                         if ((item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) && unusedScr🔵
2163                             unusedScreens.remove(screenId);                                              
2164                         }                                                                                
2165                     }                                                                                    
2166                     // If there are any empty screens remove them, and update.                           
2167                     if (unusedScreens.size() != 0) {                                                     
2168                         // Log to disk                                                                   
2169                         Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " + TextUti🔵
2170                         sBgWorkspaceScreens.removeAll(unusedScreens);                                    
2171                         updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                        
2172                     }                                                                                    
2173                 }                                                                                        
2174                 if (DEBUG_LOADERS) {                                                                     
2175                     Log.d(TAG, ("loaded workspace in " + (SystemClock.uptimeMillis() - t)) + "ms");      
2176                     Log.d(TAG, "workspace layout: ");                                                    
2177                     int nScreens = occupied.size();                                                      
2178                     for (int y = 0; y < countY; y++) {                                                   
2179                         String line = "";                                                                
2180                         Iterator<Long> iter = occupied.keySet().iterator();                              
2181                         while (iter.hasNext()) {                                                         
2182                             long screenId = iter.next();                                                 
2183                             if (screenId > 0) {                                                          
2184                                 line += " | ";                                                           
2185                             }                                                                            
2186                             for (int x = 0; x < countX; x++) {                                           
2187                                 ItemInfo[][] screen = occupied.get(screenId);                            
2188                                 if ((x < screen.length) && (y < screen[x].length)) {                     
2189                                     line += (screen[x][y] != null) ? "#" : ".";                          
2190                                 } else {                                                                 
2191                                     line += "!";                                                         
2192                                 }                                                                        
2193                             }                                                                            
2194                         }                                                                                
2195                         Log.d(TAG, ("[ " + line) + " ]");                                                
2196                     }                                                                                    
2197                 }                                                                                        
2198             }                                                                                            
2199             return loadedOldDb;                                                                          
2200         }                                                                                                
2201                                                                                                          
2202         /** Filters the set of items who are directly or indirectly (via another container) on the       
2203          * specified screen. */                                                                          
2204         private void filterCurrentWorkspaceItems(long currentScreenId, ArrayList<ItemInfo> allWorkspaceIt🔵
2205             // Purge any null ItemInfos                                                                  
2206             Iterator<ItemInfo> iter = allWorkspaceItems.iterator();                                      
2207             while (iter.hasNext()) {                                                                     
2208                 ItemInfo i = iter.next();                                                                
2209                 if (i == null) {                                                                         
2210                     iter.remove();                                                                       
2211                 }                                                                                        
2212             }                                                                                            
2213             // Order the set of items by their containers first, this allows use to walk through the     
2214             // list sequentially, build up a list of containers that are in the specified screen,        
2215             // as well as all items in those containers.                                                 
2216             Set<Long> itemsOnScreen = new HashSet<Long>();                                               
2217             Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {                             
2218                 @Override                                                                                
2219                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
2220                     return ((int) (lhs.container - rhs.container));                                      
2221                 }                                                                                        
2222             });                                                                                          
2223             for (ItemInfo info : allWorkspaceItems) {                                                    
2224                 if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                    
2225                     if (info.screenId == currentScreenId) {                                              
2226                         currentScreenItems.add(info);                                                    
2227                         itemsOnScreen.add(info.id);                                                      
2228                     } else {                                                                             
2229                         otherScreenItems.add(info);                                                      
2230                     }                                                                                    
2231                 } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {             
2232                     currentScreenItems.add(info);                                                        
2233                     itemsOnScreen.add(info.id);                                                          
2234                 } else if (itemsOnScreen.contains(info.container)) {                                     
2235                     currentScreenItems.add(info);                                                        
2236                     itemsOnScreen.add(info.id);                                                          
2237                 } else {                                                                                 
2238                     otherScreenItems.add(info);                                                          
2239                 }                                                                                        
2240             }                                                                                            
2241         }                                                                                                
2242                                                                                                          
2243         /** Filters the set of widgets which are on the specified screen. */                             
2244         private void filterCurrentAppWidgets(long currentScreenId, ArrayList<LauncherAppWidgetInfo> appWi🔵
2245             for (LauncherAppWidgetInfo widget : appWidgets) {                                            
2246                 if (widget == null) {                                                                    
2247                     continue;                                                                            
2248                 }                                                                                        
2249                 if ((widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) && (widget.screenI🔵
2250                     currentScreenWidgets.add(widget);                                                    
2251                 } else {                                                                                 
2252                     otherScreenWidgets.add(widget);                                                      
2253                 }                                                                                        
2254             }                                                                                            
2255         }                                                                                                
2256                                                                                                          
2257         /** Filters the set of folders which are on the specified screen. */                             
2258         private void filterCurrentFolders(long currentScreenId, HashMap<Long, ItemInfo> itemsIdMap, HashM🔵
2259             for (long id : folders.keySet()) {                                                           
2260                 ItemInfo info = itemsIdMap.get(id);                                                      
2261                 FolderInfo folder = folders.get(id);                                                     
2262                 if ((info == null) || (folder == null)) {                                                
2263                     continue;                                                                            
2264                 }                                                                                        
2265                 if ((info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) && (info.screenId ==🔵
2266                     currentScreenFolders.put(id, folder);                                                
2267                 } else {                                                                                 
2268                     otherScreenFolders.put(id, folder);                                                  
2269                 }                                                                                        
2270             }                                                                                            
2271         }                                                                                                
2272                                                                                                          
2273         /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to          
2274          * right) */                                                                                     
2275         private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {                   
2276             final LauncherAppState app = LauncherAppState.getInstance();                                 
2277             final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                          
2278             // XXX: review this                                                                          
2279             Collections.sort(workspaceItems, new Comparator<ItemInfo>() {                                
2280                 @Override                                                                                
2281                 public int compare(ItemInfo lhs, ItemInfo rhs) {                                         
2282                     int cellCountX = ((int) (grid.numColumns));                                          
2283                     int cellCountY = ((int) (grid.numRows));                                             
2284                     int screenOffset = cellCountX * cellCountY;                                          
2285                     int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1);// +1 hotseat       
2286                                                                                                          
2287                     long lr = (((lhs.container * containerOffset) + (lhs.screenId * screenOffset)) + (lhs🔵
2288                     long rr = (((rhs.container * containerOffset) + (rhs.screenId * screenOffset)) + (rhs🔵
2289                     return ((int) (lr - rr));                                                            
2290                 }                                                                                        
2291             });                                                                                          
2292         }                                                                                                
2293                                                                                                          
2294         private void bindWorkspaceScreens(final Callbacks oldCallbacks,                                  
2295                 final ArrayList<Long> orderedScreens) {                                                  
2296             final Runnable r = new Runnable() {                                                          
2297                 @Override                                                                                
2298                 public void run() {                                                                      
2299                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2300                     if (callbacks != null) {                                                             
2301                         callbacks.bindScreens(orderedScreens);                                           
2302                     }                                                                                    
2303                 }                                                                                        
2304             };                                                                                           
2305             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
2306         }                                                                                                
2307                                                                                                          
2308         private void bindWorkspaceItems(final Callbacks oldCallbacks, final ArrayList<ItemInfo> workspace🔵
2309             final boolean postOnMainThread = deferredBindRunnables != null;                              
2310             // Bind the workspace items                                                                  
2311             int N = workspaceItems.size();                                                               
2312             for (int i = 0; i < N; i += ITEMS_CHUNK) {                                                   
2313                 final int start = i;                                                                     
2314                 final int chunkSize = ((i + ITEMS_CHUNK) <= N) ? ITEMS_CHUNK : N - i;                    
2315                 final Runnable r = new Runnable() {                                                      
2316                     @Override                                                                            
2317                     public void run() {                                                                  
2318                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2319                         if (callbacks != null) {                                                         
2320                             callbacks.bindItems(workspaceItems, start, start + chunkSize, false);        
2321                         }                                                                                
2322                     }                                                                                    
2323                 };                                                                                       
2324                 if (postOnMainThread) {                                                                  
2325                     synchronized(deferredBindRunnables) {                                                
2326                         deferredBindRunnables.add(r);                                                    
2327                     }                                                                                    
2328                 } else {                                                                                 
2329                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2330                 }                                                                                        
2331             }                                                                                            
2332             // Bind the folders                                                                          
2333             if (!folders.isEmpty()) {                                                                    
2334                 final Runnable r = new Runnable() {                                                      
2335                     public void run() {                                                                  
2336                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2337                         if (callbacks != null) {                                                         
2338                             callbacks.bindFolders(folders);                                              
2339                         }                                                                                
2340                     }                                                                                    
2341                 };                                                                                       
2342                 if (postOnMainThread) {                                                                  
2343                     synchronized(deferredBindRunnables) {                                                
2344                         deferredBindRunnables.add(r);                                                    
2345                     }                                                                                    
2346                 } else {                                                                                 
2347                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2348                 }                                                                                        
2349             }                                                                                            
2350             // Bind the widgets, one at a time                                                           
2351             N = appWidgets.size();                                                                       
2352             for (int i = 0; i < N; i++) {                                                                
2353                 final LauncherAppWidgetInfo widget = appWidgets.get(i);                                  
2354                 final Runnable r = new Runnable() {                                                      
2355                     public void run() {                                                                  
2356                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2357                         if (callbacks != null) {                                                         
2358                             callbacks.bindAppWidget(widget);                                             
2359                         }                                                                                
2360                     }                                                                                    
2361                 };                                                                                       
2362                 if (postOnMainThread) {                                                                  
2363                     deferredBindRunnables.add(r);                                                        
2364                 } else {                                                                                 
2365                     runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                    
2366                 }                                                                                        
2367             }                                                                                            
2368         }                                                                                                
2369                                                                                                          
2370         /**                                                                                              
2371          * Binds all loaded data to actual views on the main thread.                                     
2372          */                                                                                              
2373         private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {               
2374             final long t = SystemClock.uptimeMillis();                                                   
2375             Runnable r;                                                                                  
2376             // Don't use these two variables in any of the callback runnables.                           
2377             // Otherwise we hold a reference to them.                                                    
2378             final Callbacks oldCallbacks = mCallbacks.get();                                             
2379             if (oldCallbacks == null) {                                                                  
2380                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2381                 Log.w(TAG, "LoaderTask running with no launcher");                                       
2382                 return;                                                                                  
2383             }                                                                                            
2384             // Save a copy of all the bg-thread collections                                              
2385             ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();                              
2386             ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<LauncherAppWidgetInfo>();        
2387             HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();                         
2388             HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();                          
2389             ArrayList<Long> orderedScreenIds = new ArrayList<Long>();                                    
2390             synchronized(sBgLock) {                                                                      
2391                 workspaceItems.addAll(sBgWorkspaceItems);                                                
2392                 appWidgets.addAll(sBgAppWidgets);                                                        
2393                 folders.putAll(sBgFolders);                                                              
2394                 itemsIdMap.putAll(sBgItemsIdMap);                                                        
2395                 orderedScreenIds.addAll(sBgWorkspaceScreens);                                            
2396             }                                                                                            
2397             final boolean isLoadingSynchronously = synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;
2398             int currScreen = (isLoadingSynchronously) ? synchronizeBindPage : oldCallbacks.getCurrentWork🔵
2399             if (currScreen >= orderedScreenIds.size()) {                                                 
2400                 // There may be no workspace screens (just hotseat items and an empty page).             
2401                 currScreen = PagedView.INVALID_RESTORE_PAGE;                                             
2402             }                                                                                            
2403             final int currentScreen = currScreen;                                                        
2404             final long currentScreenId = (currentScreen < 0) ? INVALID_SCREEN_ID : orderedScreenIds.get(c🔵
2405             // Load all the items that are on the current page first (and in the process, unbind         
2406             // all the existing workspace items before we call startBinding() below.                     
2407             unbindWorkspaceItemsOnMainThread();                                                          
2408             // Separate the items that are on the current screen, and all the other remaining items      
2409             ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();                       
2410             ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();                         
2411             ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<LauncherAppWidgetInfo>(); 
2412             ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<LauncherAppWidgetInfo>();   
2413             HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();                  
2414             HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();                    
2415             filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems, otherWork🔵
2416             filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets, otherAppWidgets);    
2417             filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders, otherFolders);    
2418             sortWorkspaceItemsSpatially(currentWorkspaceItems);                                          
2419             sortWorkspaceItemsSpatially(otherWorkspaceItems);                                            
2420             // Tell the workspace that we're about to start binding items                                
2421             r = new Runnable() {                                                                         
2422                 public void run() {                                                                      
2423                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2424                     if (callbacks != null) {                                                             
2425                         callbacks.startBinding();                                                        
2426                     }                                                                                    
2427                 }                                                                                        
2428             };                                                                                           
2429             runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                            
2430             bindWorkspaceScreens(oldCallbacks, orderedScreenIds);                                        
2431             // Load items on the current page                                                            
2432             bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets, currentFolders, nu🔵
2433             if (isLoadingSynchronously) {                                                                
2434                 r = new Runnable() {                                                                     
2435                     public void run() {                                                                  
2436                         Callbacks callbacks = tryGetCallbacks(oldCallbacks);                             
2437                         if ((callbacks != null) && (currentScreen != PagedView.INVALID_RESTORE_PAGE)) {  
2438                             callbacks.onPageBoundSynchronously(currentScreen);                           
2439                         }                                                                                
2440                     }                                                                                    
2441                 };                                                                                       
2442                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
2443             }                                                                                            
2444             // Load all the remaining pages (if we are loading synchronously, we want to defer this      
2445             // work until after the first render)                                                        
2446             synchronized(mDeferredBindRunnables) {                                                       
2447                 mDeferredBindRunnables.clear();                                                          
2448             }                                                                                            
2449             bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders, isLoadin🔵
2450             // Tell the workspace that we're done binding items                                          
2451             r = new Runnable() {                                                                         
2452                 public void run() {                                                                      
2453                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                 
2454                     if (callbacks != null) {                                                             
2455                         callbacks.finishBindingItems(isUpgradePath);                                     
2456                     }                                                                                    
2457                     // If we're profiling, ensure this is the last thing in the queue.                   
2458                     if (DEBUG_LOADERS) {                                                                 
2459                         Log.d(TAG, ("bound workspace in " + (SystemClock.uptimeMillis() - t)) + "ms");   
2460                     }                                                                                    
2461                     mIsLoadingAndBindingWorkspace = false;                                               
2462                 }                                                                                        
2463             };                                                                                           
2464             if (isLoadingSynchronously) {                                                                
2465                 synchronized(mDeferredBindRunnables) {                                                   
2466                     mDeferredBindRunnables.add(r);                                                       
2467                 }                                                                                        
2468             } else {                                                                                     
2469                 runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                        
2470             }                                                                                            
2471         }                                                                                                
2472                                                                                                          
2473         private void loadAndBindAllApps() {                                                              
2474             if (DEBUG_LOADERS) {                                                                         
2475                 Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);                       
2476             }                                                                                            
2477             if (!mAllAppsLoaded) {                                                                       
2478                 loadAllApps();                                                                           
2479                 synchronized (LoaderTask.this) {                                                         
2480                     if (mStopped) {                                                                      
2481                         return;                                                                          
2482                     }                                                                                    
2483                     mAllAppsLoaded = true;                                                               
2484                 }                                                                                        
2485             } else {                                                                                     
2486                 onlyBindAllApps();                                                                       
2487             }                                                                                            
2488         }                                                                                                
2489                                                                                                          
2490         private void onlyBindAllApps() {                                                                 
2491             final Callbacks oldCallbacks = mCallbacks.get();                                             
2492             if (oldCallbacks == null) {                                                                  
2493                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2494                 Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");                     
2495                 return;                                                                                  
2496             }                                                                                            
2497             // shallow copy                                                                              
2498             @SuppressWarnings("unchecked")                                                               
2499             final ArrayList<AppInfo> list = ((ArrayList<AppInfo>) (mBgAllAppsList.data.clone()));        
2500             Runnable r = new Runnable() {                                                                
2501                 public void run() {                                                                      
2502                     final long t = SystemClock.uptimeMillis();                                           
2503                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
2504                     if (callbacks != null) {                                                             
2505                         callbacks.bindAllApplications(list);                                             
2506                     }                                                                                    
2507                     if (DEBUG_LOADERS) {                                                                 
2508                         Log.d(TAG, ((("bound all " + list.size()) + " apps from cache in ") + (SystemCloc🔵
2509                     }                                                                                    
2510                 }                                                                                        
2511             };                                                                                           
2512             boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());           
2513             if (isRunningOnMainThread) {                                                                 
2514                 r.run();                                                                                 
2515             } else {                                                                                     
2516                 mHandler.post(r);                                                                        
2517             }                                                                                            
2518         }                                                                                                
2519                                                                                                          
2520         private void loadAllApps() {                                                                     
2521             final long loadTime = (DEBUG_LOADERS) ? SystemClock.uptimeMillis() : 0;                      
2522             final Callbacks oldCallbacks = mCallbacks.get();                                             
2523             if (oldCallbacks == null) {                                                                  
2524                 // This launcher has exited and nobody bothered to tell us.  Just bail.                  
2525                 Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");                         
2526                 return;                                                                                  
2527             }                                                                                            
2528             final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);                              
2529             mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                            
2530             final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();                      
2531             // Clear the list of apps                                                                    
2532             mBgAllAppsList.clear();                                                                      
2533             for (UserHandleCompat user : profiles) {                                                     
2534                 // Query for the set of apps                                                             
2535                 final long qiaTime = (DEBUG_LOADERS) ? SystemClock.uptimeMillis() : 0;                   
2536                 List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);       
2537                 if (DEBUG_LOADERS) {                                                                     
2538                     Log.d(TAG, (("getActivityList took " + (SystemClock.uptimeMillis() - qiaTime)) + "ms 🔵
2539                     Log.d(TAG, (("getActivityList got " + apps.size()) + " apps for user ") + user);     
2540                 }                                                                                        
2541             // Fail if we don't have any apps                                                            
2542                 if ((apps == null) || apps.isEmpty()) {                                                  
2543                     return;                                                                              
2544                 }                                                                                        
2545                 // Sort the applications by name                                                         
2546                 final long sortTime = (DEBUG_LOADERS) ? SystemClock.uptimeMillis() : 0;                  
2547                 Collections.sort(apps, new LauncherModel.ShortcutNameComparator(mLabelCache));           
2548                 if (DEBUG_LOADERS) {                                                                     
2549                     Log.d(TAG, ("sort took " + (SystemClock.uptimeMillis() - sortTime)) + "ms");         
2550                 }                                                                                        
2551             // Create the ApplicationInfos                                                               
2552                 for (int i = 0; i < apps.size(); i++) {                                                  
2553                     LauncherActivityInfoCompat app = apps.get(i);                                        
2554                 // This builds the icon bitmaps.                                                         
2555                     mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));       
2556                 }                                                                                        
2557             }                                                                                            
2558             // Huh? Shouldn't this be inside the Runnable below?                                         
2559             final ArrayList<AppInfo> added = mBgAllAppsList.added;                                       
2560             mBgAllAppsList.added = new ArrayList<AppInfo>();                                             
2561             // Post callback on main thread                                                              
2562             mHandler.post(new Runnable() {                                                               
2563                 public void run() {                                                                      
2564                     final long bindTime = SystemClock.uptimeMillis();                                    
2565                     final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                           
2566                     if (callbacks != null) {                                                             
2567                         callbacks.bindAllApplications(added);                                            
2568                         if (DEBUG_LOADERS) {                                                             
2569                             Log.d(TAG, ((("bound " + added.size()) + " apps in ") + (SystemClock.uptimeMi🔵
2570                         }                                                                                
2571                     } else {                                                                             
2572                         Log.i(TAG, "not binding apps: no Launcher activity");                            
2573                     }                                                                                    
2574                 }                                                                                        
2575             });                                                                                          
2576             if (DEBUG_LOADERS) {                                                                         
2577                 Log.d(TAG, ("Icons processed in " + (SystemClock.uptimeMillis() - loadTime)) + "ms");    
2578             }                                                                                            
2579         }                                                                                                
2580                                                                                                          
2581         public void dumpState() {                                                                        
2582             synchronized(sBgLock) {                                                                      
2583                 Log.d(TAG, "mLoaderTask.mContext=" + mContext);                                          
2584                 Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);                                  
2585                 Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);                                          
2586                 Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);          
2587                 Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());                                   
2588             }                                                                                            
2589         }                                                                                                
2590     }                                                                                                    
2591                                                                                                          
2592     void enqueuePackageUpdated(PackageUpdatedTask task) {                                                
2593         sWorker.post(task);                                                                              
2594     }                                                                                                    
2595                                                                                                          
2596     private class AppsAvailabilityCheck extends BroadcastReceiver {                                      
2597         @Override                                                                                        
2598         public void onReceive(Context context, Intent intent) {                                          
2599             synchronized(sBgLock) {                                                                      
2600                 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mApp.getContext())🔵
2601                 ArrayList<String> packagesRemoved;                                                       
2602                 for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {     
2603                     UserHandleCompat user = entry.getKey();                                              
2604                     packagesRemoved = new ArrayList<String>();                                           
2605                     for (String pkg : entry.getValue()) {                                                
2606                         if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {                       
2607                             Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);                 
2608                             packagesRemoved.add(pkg);                                                    
2609                         }                                                                                
2610                     }                                                                                    
2611                     if (!packagesRemoved.isEmpty()) {                                                    
2612                         enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE, packag🔵
2613                     }                                                                                    
2614                 }                                                                                        
2615                 sPendingPackages.clear();                                                                
2616             }                                                                                            
2617         }                                                                                                
2618     }                                                                                                    
2619                                                                                                          
2620     /**                                                                                                  
2621      * Workaround to re-check unrestored items, in-case they were installed but the Package-ADD          
2622      * runnable was missed by the launcher.                                                              
2623      */                                                                                                  
2624     public void recheckRestoredItems(final Context context) {                                            
2625         Runnable r = new Runnable() {                                                                    
2626             @Override                                                                                    
2627             public void run() {                                                                          
2628                 LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);               
2629                 HashSet<String> installedPackages = new HashSet<String>();                               
2630                 UserHandleCompat user = UserHandleCompat.myUserHandle();                                 
2631                 synchronized(sBgLock) {                                                                  
2632                     for (ItemInfo info : sBgItemsIdMap.values()) {                                       
2633                         if (info instanceof ShortcutInfo) {                                              
2634                             ShortcutInfo si = ((ShortcutInfo) (info));                                   
2635                             if ((si.isPromise() && (si.getTargetComponent() != null)) && launcherApps.isP🔵
2636                                 installedPackages.add(si.getTargetComponent().getPackageName());         
2637                             }                                                                            
2638                         } else if (info instanceof LauncherAppWidgetInfo) {                              
2639                             LauncherAppWidgetInfo widget = ((LauncherAppWidgetInfo) (info));             
2640                             if (widget.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) && l🔵
2641                                 installedPackages.add(widget.providerName.getPackageName());             
2642                             }                                                                            
2643                         }                                                                                
2644                     }                                                                                    
2645                 }                                                                                        
2646                 if (!installedPackages.isEmpty()) {                                                      
2647                     final ArrayList<AppInfo> restoredApps = new ArrayList<AppInfo>();                    
2648                     for (String pkg : installedPackages) {                                               
2649                         for (LauncherActivityInfoCompat info : launcherApps.getActivityList(pkg, user)) {
2650                             restoredApps.add(new AppInfo(context, info, user, mIconCache, null));        
2651                         }                                                                                
2652                     }                                                                                    
2653                     final Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;          
2654                     if (!restoredApps.isEmpty()) {                                                       
2655                         mHandler.post(new Runnable() {                                                   
2656                             public void run() {                                                          
2657                                 Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;           
2658                                 if ((callbacks == cb) && (cb != null)) {                                 
2659                                     callbacks.bindAppsRestored(restoredApps);                            
2660                                 }                                                                        
2661                             }                                                                            
2662                         });                                                                              
2663                     }                                                                                    
2664                 }                                                                                        
2665             }                                                                                            
2666         };                                                                                               
2667         sWorker.post(r);                                                                                 
2668     }                                                                                                    
2669                                                                                                          
2670     private class PackageUpdatedTask implements Runnable {                                               
2671         int mOp;                                                                                         
2672                                                                                                          
2673         String[] mPackages;                                                                              
2674                                                                                                          
2675         UserHandleCompat mUser;                                                                          
2676                                                                                                          
2677         public static final int OP_NONE = 0;                                                             
2678                                                                                                          
2679         public static final int OP_ADD = 1;                                                              
2680                                                                                                          
2681         public static final int OP_UPDATE = 2;                                                           
2682                                                                                                          
2683         // uninstlled                                                                                    
2684         public static final int OP_REMOVE = 3; // uninstlled                                             
2685                                                                                                          
2686         // external media unmounted                                                                      
2687         public static final int OP_UNAVAILABLE = 4; // external media unmounted                          
2688                                                                                                          
2689         public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {                    
2690             mOp = op;                                                                                    
2691             mPackages = packages;                                                                        
2692             mUser = user;                                                                                
2693         }                                                                                                
2694                                                                                                          
2695         public void run() {                                                                              
2696             final Context context = mApp.getContext();                                                   
2697             final String[] packages = mPackages;                                                         
2698             final int N = packages.length;                                                               
2699             switch (mOp) {                                                                               
2700                 case OP_ADD :                                                                            
2701                     for (int i = 0; i < N; i++) {                                                        
2702                         if (DEBUG_LOADERS) {                                                             
2703                             Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);                        
2704                         }                                                                                
2705                         mIconCache.remove(packages[i], mUser);                                           
2706                         mBgAllAppsList.addPackage(context, packages[i], mUser);                          
2707                     }                                                                                    
2708                     break;                                                                               
2709                 case OP_UPDATE :                                                                         
2710                     for (int i = 0; i < N; i++) {                                                        
2711                         if (DEBUG_LOADERS) {                                                             
2712                             Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);                     
2713                         }                                                                                
2714                         mBgAllAppsList.updatePackage(context, packages[i], mUser);                       
2715                         WidgetPreviewLoader.removePackageFromDb(mApp.getWidgetPreviewCacheDb(), packages[🔵
2716                     }                                                                                    
2717                     break;                                                                               
2718                 case OP_REMOVE :                                                                         
2719                 case OP_UNAVAILABLE :                                                                    
2720                     for (int i = 0; i < N; i++) {                                                        
2721                         if (DEBUG_LOADERS) {                                                             
2722                             Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);                     
2723                         }                                                                                
2724                         mBgAllAppsList.removePackage(packages[i], mUser);                                
2725                         WidgetPreviewLoader.removePackageFromDb(mApp.getWidgetPreviewCacheDb(), packages[🔵
2726                     }                                                                                    
2727                     break;                                                                               
2728             }                                                                                            
2729             ArrayList<AppInfo> added = null;                                                             
2730             ArrayList<AppInfo> modified = null;                                                          
2731             final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();                             
2732             if (mBgAllAppsList.added.size() > 0) {                                                       
2733                 added = new ArrayList<AppInfo>(mBgAllAppsList.added);                                    
2734                 mBgAllAppsList.added.clear();                                                            
2735             }                                                                                            
2736             if (mBgAllAppsList.modified.size() > 0) {                                                    
2737                 modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);                              
2738                 mBgAllAppsList.modified.clear();                                                         
2739             }                                                                                            
2740             if (mBgAllAppsList.removed.size() > 0) {                                                     
2741                 removedApps.addAll(mBgAllAppsList.removed);                                              
2742                 mBgAllAppsList.removed.clear();                                                          
2743             }                                                                                            
2744             final Callbacks callbacks = (mCallbacks != null) ? mCallbacks.get() : null;                  
2745             if (callbacks == null) {                                                                     
2746                 Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");          
2747                 return;                                                                                  
2748             }                                                                                            
2749             if (added != null) {                                                                         
2750                 // Ensure that we add all the workspace applications to the db                           
2751                 if (LauncherAppState.isDisableAllApps()) {                                               
2752                     final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);               
2753                     addAndBindAddedWorkspaceApps(context, addedInfos);                                   
2754                 } else {                                                                                 
2755                     addAppsToAllApps(context, added);                                                    
2756                 }                                                                                        
2757             }                                                                                            
2758             if (modified != null) {                                                                      
2759                 final ArrayList<AppInfo> modifiedFinal = modified;                                       
2760                 // Update the launcher db to reflect the changes                                         
2761                 for (AppInfo a : modifiedFinal) {                                                        
2762                     ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);     
2763                     for (ItemInfo i : infos) {                                                           
2764                         if (isShortcutInfoUpdateable(i)) {                                               
2765                             ShortcutInfo info = ((ShortcutInfo) (i));                                    
2766                             info.title = a.title.toString();                                             
2767                             info.contentDescription = a.contentDescription;                              
2768                             updateItemInDatabase(context, info);                                         
2769                         }                                                                                
2770                     }                                                                                    
2771                 }                                                                                        
2772                 mHandler.post(new Runnable() {                                                           
2773                     public void run() {                                                                  
2774                         Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;                   
2775                         if ((callbacks == cb) && (cb != null)) {                                         
2776                             callbacks.bindAppsUpdated(modifiedFinal);                                    
2777                         }                                                                                
2778                     }                                                                                    
2779                 });                                                                                      
2780             }                                                                                            
2781             final ArrayList<String> removedPackageNames = new ArrayList<String>();                       
2782             if (mOp == OP_REMOVE) {                                                                      
2783                 // Mark all packages in the broadcast to be removed                                      
2784                 removedPackageNames.addAll(Arrays.asList(packages));                                     
2785             } else if (mOp == OP_UPDATE) {                                                               
2786                 // Mark disabled packages in the broadcast to be removed                                 
2787                 final PackageManager pm = context.getPackageManager();                                   
2788                 for (int i = 0; i < N; i++) {                                                            
2789                     if (isPackageDisabled(context, packages[i], mUser)) {                                
2790                         removedPackageNames.add(packages[i]);                                            
2791                     }                                                                                    
2792                 }                                                                                        
2793             }                                                                                            
2794             // Remove all the components associated with this package                                    
2795             for (String pn : removedPackageNames) {                                                      
2796                 deletePackageFromDatabase(context, pn, mUser);                                           
2797             }                                                                                            
2798             // Remove all the specific components                                                        
2799             for (AppInfo a : removedApps) {                                                              
2800                 ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);         
2801                 deleteItemsFromDatabase(context, infos);                                                 
2802             }                                                                                            
2803             if ((!removedPackageNames.isEmpty()) || (!removedApps.isEmpty())) {                          
2804                 // Remove any queued items from the install queue                                        
2805                 String spKey = LauncherAppState.getSharedPreferencesKey();                               
2806                 SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);        
2807                 InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);                 
2808                 // Call the components-removed callback                                                  
2809                 mHandler.post(new Runnable() {                                                           
2810                     public void run() {                                                                  
2811                         Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;                   
2812                         if ((callbacks == cb) && (cb != null)) {                                         
2813                             callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);    
2814                         }                                                                                
2815                     }                                                                                    
2816                 });                                                                                      
2817             }                                                                                            
2818             final ArrayList<Object> widgetsAndShortcuts = getSortedWidgetsAndShortcuts(context);         
2819             mHandler.post(new Runnable() {                                                               
2820                 @Override                                                                                
2821                 public void run() {                                                                      
2822                     Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;                       
2823                     if ((callbacks == cb) && (cb != null)) {                                             
2824                         callbacks.bindPackagesUpdated(widgetsAndShortcuts);                              
2825                     }                                                                                    
2826                 }                                                                                        
2827             });                                                                                          
2828             // Write all the logs to disk                                                                
2829             mHandler.post(new Runnable() {                                                               
2830                 public void run() {                                                                      
2831                     Callbacks cb = (mCallbacks != null) ? mCallbacks.get() : null;                       
2832                     if ((callbacks == cb) && (cb != null)) {                                             
2833                         callbacks.dumpLogsToLocalData();                                                 
2834                     }                                                                                    
2835                 }                                                                                        
2836             });                                                                                          
2837         }                                                                                                
2838     }                                                                                                    
2839                                                                                                          
2840     // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                     
2841     public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                      
2842         PackageManager packageManager = context.getPackageManager();                                     
2843         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                           
2844         widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());       
2845         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                              
2846         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));            
2847         Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));             
2848         return widgetsAndShortcuts;                                                                      
2849     }                                                                                                    
2850                                                                                                          
2851     private static boolean isPackageDisabled(Context context, String packageName, UserHandleCompat user) 🔵
2852         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
2853         return !launcherApps.isPackageEnabledForProfile(packageName, user);                              
2854     }                                                                                                    
2855                                                                                                          
2856     public static boolean isValidPackageActivity(Context context, ComponentName cn, UserHandleCompat user🔵
2857         if (cn == null) {                                                                                
2858             return false;                                                                                
2859         }                                                                                                
2860         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
2861         if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {                       
2862             return false;                                                                                
2863         }                                                                                                
2864         return launcherApps.isActivityEnabledForProfile(cn, user);                                       
2865     }                                                                                                    
2866                                                                                                          
2867     public static boolean isValidPackage(Context context, String packageName, UserHandleCompat user) {   
2868         if (packageName == null) {                                                                       
2869             return false;                                                                                
2870         }                                                                                                
2871         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                 
2872         return launcherApps.isPackageEnabledForProfile(packageName, user);                               
2873     }                                                                                                    
2874                                                                                                          
2875     /**                                                                                                  
2876      * Make an ShortcutInfo object for a restored application or shortcut item that points               
2877      * to a package that is not yet installed on the system.                                             
2878      */                                                                                                  
2879     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent, int promiseType🔵
2880         final ShortcutInfo info = new ShortcutInfo();                                                    
2881         info.user = UserHandleCompat.myUserHandle();                                                     
2882         mIconCache.getTitleAndIcon(info, intent, info.user, true);                                       
2883         if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {                                      
2884             String title = (cursor != null) ? cursor.getString(titleIndex) : null;                       
2885             if (!TextUtils.isEmpty(title)) {                                                             
2886                 info.title = title;                                                                      
2887             }                                                                                            
2888             info.status = ShortcutInfo.FLAG_RESTORED_ICON;                                               
2889         } else if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {                             
2890             if (TextUtils.isEmpty(info.title)) {                                                         
2891                 info.title = (cursor != null) ? cursor.getString(titleIndex) : "";                       
2892             }                                                                                            
2893             info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;                                             
2894         } else {                                                                                         
2895             throw new InvalidParameterException("Invalid restoreType " + promiseType);                   
2896         }                                                                                                
2897         info.contentDescription = mUserManager.getBadgedLabelForUser(info.title.toString(), info.user);  
2898         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
2899         info.promisedIntent = intent;                                                                    
2900         return info;                                                                                     
2901     }                                                                                                    
2902                                                                                                          
2903     /**                                                                                                  
2904      * Make an Intent object for a restored application or shortcut item that points                     
2905      * to the market page for the item.                                                                  
2906      */                                                                                                  
2907     private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                     
2908         ComponentName componentName = intent.getComponent();                                             
2909         return getMarketIntent(componentName.getPackageName());                                          
2910     }                                                                                                    
2911                                                                                                          
2912     static Intent getMarketIntent(String packageName) {                                                  
2913         return new Intent(Intent.ACTION_VIEW).setData(new Uri.Builder().scheme("market").authority("detai🔵
2914     }                                                                                                    
2915                                                                                                          
2916     /**                                                                                                  
2917      * This is called from the code that adds shortcuts from the intent receiver.  This                  
2918      * doesn't have a Cursor, but                                                                        
2919      */                                                                                                  
2920     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, UserHandleCompat user, Con🔵
2921         return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);               
2922     }                                                                                                    
2923                                                                                                          
2924     /**                                                                                                  
2925      * Make an ShortcutInfo object for a shortcut that is an application.                                
2926      *                                                                                                   
2927      * If c is not null, then it will be used to fill in missing data like the title and icon.           
2928      */                                                                                                  
2929     public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, UserHandleCompat user, Con🔵
2930         if (user == null) {                                                                              
2931             Log.d(TAG, "Null user found in getShortcutInfo");                                            
2932             return null;                                                                                 
2933         }                                                                                                
2934         ComponentName componentName = intent.getComponent();                                             
2935         if (componentName == null) {                                                                     
2936             Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);                  
2937             return null;                                                                                 
2938         }                                                                                                
2939         Intent newIntent = new Intent(intent.getAction(), null);                                         
2940         newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                 
2941         newIntent.setComponent(componentName);                                                           
2942         LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);                 
2943         if ((lai == null) && (!allowMissingTarget)) {                                                    
2944             Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);                   
2945             return null;                                                                                 
2946         }                                                                                                
2947         final ShortcutInfo info = new ShortcutInfo();                                                    
2948         // the resource -- This may implicitly give us back the fallback icon,                           
2949         // but don't worry about that.  All we're doing with usingFallbackIcon is                        
2950         // to avoid saving lots of copies of that in the database, and most apps                         
2951         // have icons anyway.                                                                            
2952         Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);                                
2953         // the db                                                                                        
2954         if (icon == null) {                                                                              
2955             if (c != null) {                                                                             
2956                 icon = getIconFromCursor(c, iconIndex, context);                                         
2957             }                                                                                            
2958         }                                                                                                
2959         // the fallback icon                                                                             
2960         if (icon == null) {                                                                              
2961             icon = mIconCache.getDefaultIcon(user);                                                      
2962             info.usingFallbackIcon = true;                                                               
2963         }                                                                                                
2964         info.setIcon(icon);                                                                              
2965         // From the cache.                                                                               
2966         if (labelCache != null) {                                                                        
2967             info.title = labelCache.get(componentName);                                                  
2968         }                                                                                                
2969         // from the resource                                                                             
2970         if ((info.title == null) && (lai != null)) {                                                     
2971             info.title = lai.getLabel();                                                                 
2972             if (labelCache != null) {                                                                    
2973                 labelCache.put(componentName, info.title);                                               
2974             }                                                                                            
2975         }                                                                                                
2976         // from the db                                                                                   
2977         if (info.title == null) {                                                                        
2978             if (c != null) {                                                                             
2979                 info.title = c.getString(titleIndex);                                                    
2980             }                                                                                            
2981         }                                                                                                
2982         // fall back to the class name of the activity                                                   
2983         if (info.title == null) {                                                                        
2984             info.title = componentName.getClassName();                                                   
2985         }                                                                                                
2986         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                
2987         info.user = user;                                                                                
2988         info.contentDescription = mUserManager.getBadgedLabelForUser(info.title.toString(), info.user);  
2989         return info;                                                                                     
2990     }                                                                                                    
2991                                                                                                          
2992     static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos, ItemInfoFilter f) {           
2993         HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                            
2994         for (ItemInfo i : infos) {                                                                       
2995             if (i instanceof ShortcutInfo) {                                                             
2996                 ShortcutInfo info = ((ShortcutInfo) (i));                                                
2997                 ComponentName cn = info.getTargetComponent();                                            
2998                 if ((cn != null) && f.filterItem(null, info, cn)) {                                      
2999                     filtered.add(info);                                                                  
3000                 }                                                                                        
3001             } else if (i instanceof FolderInfo) {                                                        
3002                 FolderInfo info = ((FolderInfo) (i));                                                    
3003                 for (ShortcutInfo s : info.contents) {                                                   
3004                     ComponentName cn = s.getTargetComponent();                                           
3005                     if ((cn != null) && f.filterItem(info, s, cn)) {                                     
3006                         filtered.add(s);                                                                 
3007                     }                                                                                    
3008                 }                                                                                        
3009             } else if (i instanceof LauncherAppWidgetInfo) {                                             
3010                 LauncherAppWidgetInfo info = ((LauncherAppWidgetInfo) (i));                              
3011                 ComponentName cn = info.providerName;                                                    
3012                 if ((cn != null) && f.filterItem(null, info, cn)) {                                      
3013                     filtered.add(info);                                                                  
3014                 }                                                                                        
3015             }                                                                                            
3016         }                                                                                                
3017         return new ArrayList<ItemInfo>(filtered);                                                        
3018     }                                                                                                    
3019                                                                                                          
3020     private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname, final UserHandleCo🔵
3021         ItemInfoFilter filter = new ItemInfoFilter() {                                                   
3022             @Override                                                                                    
3023             public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                
3024                 if (info.user == null) {                                                                 
3025                     return cn.equals(cname);                                                             
3026                 } else {                                                                                 
3027                     return cn.equals(cname) && info.user.equals(user);                                   
3028                 }                                                                                        
3029             }                                                                                            
3030         };                                                                                               
3031         return filterItemInfos(sBgItemsIdMap.values(), filter);                                          
3032     }                                                                                                    
3033                                                                                                          
3034     public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                         
3035         if (i instanceof ShortcutInfo) {                                                                 
3036             ShortcutInfo info = ((ShortcutInfo) (i));                                                    
3037             // We need to check for ACTION_MAIN otherwise getComponent() might                           
3038             // return null for some shortcuts (for instance, for shortcuts to                            
3039             // web pages.)                                                                               
3040             Intent intent = info.intent;                                                                 
3041             ComponentName name = intent.getComponent();                                                  
3042             if (((info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) && Intent.ACTION_MAI🔵
3043                 return true;                                                                             
3044             }                                                                                            
3045             // placeholder shortcuts get special treatment, let them through too.                        
3046             if (info.isPromise()) {                                                                      
3047                 return true;                                                                             
3048             }                                                                                            
3049         }                                                                                                
3050         return false;                                                                                    
3051     }                                                                                                    
3052                                                                                                          
3053     /**                                                                                                  
3054      * Make an ShortcutInfo object for a shortcut that isn't an application.                             
3055      */                                                                                                  
3056     private ShortcutInfo getShortcutInfo(Cursor c, Context context, int iconTypeIndex, int iconPackageInd🔵
3057         Bitmap icon = null;                                                                              
3058         final ShortcutInfo info = new ShortcutInfo();                                                    
3059         // Non-app shortcuts are only supported for current user.                                        
3060         info.user = UserHandleCompat.myUserHandle();                                                     
3061         info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                   
3062         // TODO: If there's an explicit component and we can't install that, delete it.                  
3063         info.title = c.getString(titleIndex);                                                            
3064         int iconType = c.getInt(iconTypeIndex);                                                          
3065         switch (iconType) {                                                                              
3066             case LauncherSettings.Favorites.ICON_TYPE_RESOURCE :                                         
3067                 String packageName = c.getString(iconPackageIndex);                                      
3068                 String resourceName = c.getString(iconResourceIndex);                                    
3069                 PackageManager packageManager = context.getPackageManager();                             
3070                 info.customIcon = false;                                                                 
3071             // the resource                                                                              
3072                 try {                                                                                    
3073                     Resources resources = packageManager.getResourcesForApplication(packageName);        
3074                     if (resources != null) {                                                             
3075                         final int id = resources.getIdentifier(resourceName, null, null);                
3076                         icon = Utilities.createIconBitmap(mIconCache.getFullResIcon(resources, id), conte🔵
3077                     }                                                                                    
3078                 } catch (java.lang.Exception e) {                                                        
3079                     // drop this.  we have other places to look for icons                                
3080                 }                                                                                        
3081             // the db                                                                                    
3082                 if (icon == null) {                                                                      
3083                     icon = getIconFromCursor(c, iconIndex, context);                                     
3084                 }                                                                                        
3085             // the fallback icon                                                                         
3086                 if (icon == null) {                                                                      
3087                     icon = mIconCache.getDefaultIcon(info.user);                                         
3088                     info.usingFallbackIcon = true;                                                       
3089                 }                                                                                        
3090                 break;                                                                                   
3091             case LauncherSettings.Favorites.ICON_TYPE_BITMAP :                                           
3092                 icon = getIconFromCursor(c, iconIndex, context);                                         
3093                 if (icon == null) {                                                                      
3094                     icon = mIconCache.getDefaultIcon(info.user);                                         
3095                     info.customIcon = false;                                                             
3096                     info.usingFallbackIcon = true;                                                       
3097                 } else {                                                                                 
3098                     info.customIcon = true;                                                              
3099                 }                                                                                        
3100                 break;                                                                                   
3101             default :                                                                                    
3102                 icon = mIconCache.getDefaultIcon(info.user);                                             
3103                 info.usingFallbackIcon = true;                                                           
3104                 info.customIcon = false;                                                                 
3105                 break;                                                                                   
3106         }                                                                                                
3107         info.setIcon(icon);                                                                              
3108         return info;                                                                                     
3109     }                                                                                                    
3110                                                                                                          
3111     Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                 
3112         // suppress dead code warning                                                                    
3113         @SuppressWarnings("all")                                                                         
3114         final boolean debug = false;                                                                     
3115         if (debug) {                                                                                     
3116             Log.d(TAG, "getIconFromCursor app=" + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Fa🔵
3117         }                                                                                                
3118         byte[] data = c.getBlob(iconIndex);                                                              
3119         try {                                                                                            
3120             return Utilities.createIconBitmap(BitmapFactory.decodeByteArray(data, 0, data.length), contex🔵
3121         } catch (java.lang.Exception e) {                                                                
3122             return null;                                                                                 
3123         }                                                                                                
3124     }                                                                                                    
3125                                                                                                          
3126     ShortcutInfo addShortcut(Context context, Intent data, long container, int screen, int cellX, int cel🔵
3127         final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                           
3128         if (info == null) {                                                                              
3129             return null;                                                                                 
3130         }                                                                                                
3131         addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                       
3132         return info;                                                                                     
3133     }                                                                                                    
3134                                                                                                          
3135     /**                                                                                                  
3136      * Attempts to find an AppWidgetProviderInfo that matches the given component.                       
3137      */                                                                                                  
3138     static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context, ComponentName co🔵
3139         List<AppWidgetProviderInfo> widgets = AppWidgetManager.getInstance(context).getInstalledProviders🔵
3140         for (AppWidgetProviderInfo info : widgets) {                                                     
3141             if (info.provider.equals(component)) {                                                       
3142                 return info;                                                                             
3143             }                                                                                            
3144         }                                                                                                
3145         return null;                                                                                     
3146     }                                                                                                    
3147                                                                                                          
3148     ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {             
3149         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                           
3150         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                   
3151         Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                         
3152         if (intent == null) {                                                                            
3153             // If the intent is null, we can't construct a valid ShortcutInfo, so we return null         
3154             Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                  
3155             return null;                                                                                 
3156         }                                                                                                
3157         Bitmap icon = null;                                                                              
3158         boolean customIcon = false;                                                                      
3159         ShortcutIconResource iconResource = null;                                                        
3160         if ((bitmap != null) && (bitmap instanceof Bitmap)) {                                            
3161             icon = Utilities.createIconBitmap(new FastBitmapDrawable(((Bitmap) (bitmap))), context);     
3162             customIcon = true;                                                                           
3163         } else {                                                                                         
3164             Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);             
3165             if ((extra != null) && (extra instanceof ShortcutIconResource)) {                            
3166                 try {                                                                                    
3167                     iconResource = ((ShortcutIconResource) (extra));                                     
3168                     final PackageManager packageManager = context.getPackageManager();                   
3169                     Resources resources = packageManager.getResourcesForApplication(iconResource.packageN🔵
3170                     final int id = resources.getIdentifier(iconResource.resourceName, null, null);       
3171                     icon = Utilities.createIconBitmap(mIconCache.getFullResIcon(resources, id), context);
3172                 } catch (java.lang.Exception e) {                                                        
3173                     Log.w(TAG, "Could not load shortcut icon: " + extra);                                
3174                 }                                                                                        
3175             }                                                                                            
3176         }                                                                                                
3177         final ShortcutInfo info = new ShortcutInfo();                                                    
3178         // Only support intents for current user for now. Intents sent from other                        
3179         // users wouldn't get here without intent forwarding anyway.                                     
3180         info.user = UserHandleCompat.myUserHandle();                                                     
3181         if (icon == null) {                                                                              
3182             if (fallbackIcon != null) {                                                                  
3183                 icon = fallbackIcon;                                                                     
3184             } else {                                                                                     
3185                 icon = mIconCache.getDefaultIcon(info.user);                                             
3186                 info.usingFallbackIcon = true;                                                           
3187             }                                                                                            
3188         }                                                                                                
3189         info.setIcon(icon);                                                                              
3190         info.title = name;                                                                               
3191         info.contentDescription = mUserManager.getBadgedLabelForUser(info.title.toString(), info.user);  
3192         info.intent = intent;                                                                            
3193         info.customIcon = customIcon;                                                                    
3194         info.iconResource = iconResource;                                                                
3195         return info;                                                                                     
3196     }                                                                                                    
3197                                                                                                          
3198     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c, int iconInde🔵
3199         // If apps can't be on SD, don't even bother.                                                    
3200         if (!mAppsCanBeOnRemoveableStorage) {                                                            
3201             return false;                                                                                
3202         }                                                                                                
3203         // If this icon doesn't have a custom icon, check to see                                         
3204         // what's stored in the DB, and if it doesn't match what                                         
3205         // we're going to show, store what we are going to show back                                     
3206         // into the DB.  We do this so when we're loading, if the                                        
3207         // package manager can't find an icon (for example because                                       
3208         // the app is on SD) then we can use that instead.                                               
3209         if ((!info.customIcon) && (!info.usingFallbackIcon)) {                                           
3210             cache.put(info, c.getBlob(iconIndex));                                                       
3211             return true;                                                                                 
3212         }                                                                                                
3213         return false;                                                                                    
3214     }                                                                                                    
3215                                                                                                          
3216     void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {                              
3217         boolean needSave = false;                                                                        
3218         try {                                                                                            
3219             if (data != null) {                                                                          
3220                 Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);                      
3221                 Bitmap loaded = info.getIcon(mIconCache);                                                
3222                 needSave = !saved.sameAs(loaded);                                                        
3223             } else {                                                                                     
3224                 needSave = true;                                                                         
3225             }                                                                                            
3226         } catch (java.lang.Exception e) {                                                                
3227             needSave = true;                                                                             
3228         }                                                                                                
3229         if (needSave) {                                                                                  
3230             Log.d(TAG, "going to save icon bitmap for info=" + info);                                    
3231             // This is slower than is ideal, but this only happens once                                  
3232             // or when the app is updated with a new icon.                                               
3233             updateItemInDatabase(context, info);                                                         
3234         }                                                                                                
3235     }                                                                                                    
3236                                                                                                          
3237     /**                                                                                                  
3238      * Return an existing FolderInfo object if we have encountered this ID previously,                   
3239      * or make a new one.                                                                                
3240      */                                                                                                  
3241     private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {             
3242         // See if a placeholder was created for us already                                               
3243         FolderInfo folderInfo = folders.get(id);                                                         
3244         if (folderInfo == null) {                                                                        
3245             // No placeholder -- create a new instance                                                   
3246             folderInfo = new FolderInfo();                                                               
3247             folders.put(id, folderInfo);                                                                 
3248         }                                                                                                
3249         return folderInfo;                                                                               
3250     }                                                                                                    
3251                                                                                                          
3252     public static final Comparator<AppInfo> getAppNameComparator() {                                     
3253         final Collator collator = Collator.getInstance();                                                
3254         return new Comparator<AppInfo>() {                                                               
3255             public final int compare(AppInfo a, AppInfo b) {                                             
3256                 if (a.user.equals(b.user)) {                                                             
3257                     int result = collator.compare(a.title.toString().trim(), b.title.toString().trim()); 
3258                     if (result == 0) {                                                                   
3259                         result = a.componentName.compareTo(b.componentName);                             
3260                     }                                                                                    
3261                     return result;                                                                       
3262                 } else {                                                                                 
3263                     // TODO Need to figure out rules for sorting                                         
3264                     // profiles, this puts work second.                                                  
3265                     return a.user.toString().compareTo(b.user.toString());                               
3266                 }                                                                                        
3267             }                                                                                            
3268         };                                                                                               
3269     }                                                                                                    
3270                                                                                                          
3271     public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR = new Comparator<AppInfo>() {    
3272         public final int compare(AppInfo a, AppInfo b) {                                                 
3273             if (a.firstInstallTime < b.firstInstallTime) {                                               
3274                 return 1;                                                                                
3275             }                                                                                            
3276             if (a.firstInstallTime > b.firstInstallTime) {                                               
3277                 return -1;                                                                               
3278             }                                                                                            
3279             return 0;                                                                                    
3280         }                                                                                                
3281     };                                                                                                   
3282                                                                                                          
3283     static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {                             
3284         if (info.activityInfo != null) {                                                                 
3285             return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);             
3286         } else {                                                                                         
3287             return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);               
3288         }                                                                                                
3289     }                                                                                                    
3290                                                                                                          
3291     public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {       
3292         private Collator mCollator;                                                                      
3293                                                                                                          
3294         private HashMap<Object, CharSequence> mLabelCache;                                               
3295                                                                                                          
3296         ShortcutNameComparator(PackageManager pm) {                                                      
3297             mLabelCache = new HashMap<Object, CharSequence>();                                           
3298             mCollator = Collator.getInstance();                                                          
3299         }                                                                                                
3300                                                                                                          
3301         ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {                               
3302             mLabelCache = labelCache;                                                                    
3303             mCollator = Collator.getInstance();                                                          
3304         }                                                                                                
3305                                                                                                          
3306         public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {           
3307             String labelA;                                                                               
3308             String labelB;                                                                               
3309             ComponentName keyA = a.getComponentName();                                                   
3310             ComponentName keyB = b.getComponentName();                                                   
3311             if (mLabelCache.containsKey(keyA)) {                                                         
3312                 labelA = mLabelCache.get(keyA).toString();                                               
3313             } else {                                                                                     
3314                 labelA = a.getLabel().toString().trim();                                                 
3315                 mLabelCache.put(keyA, labelA);                                                           
3316             }                                                                                            
3317             if (mLabelCache.containsKey(keyB)) {                                                         
3318                 labelB = mLabelCache.get(keyB).toString();                                               
3319             } else {                                                                                     
3320                 labelB = b.getLabel().toString().trim();                                                 
3321                 mLabelCache.put(keyB, labelB);                                                           
3322             }                                                                                            
3323             return mCollator.compare(labelA, labelB);                                                    
3324         }                                                                                                
3325     }                                                                                                    
3326                                                                                                          
3327     public static class WidgetAndShortcutNameComparator implements Comparator<Object> {                  
3328         private final AppWidgetManagerCompat mManager;                                                   
3329                                                                                                          
3330         private final PackageManager mPackageManager;                                                    
3331                                                                                                          
3332         private final HashMap<Object, String> mLabelCache;                                               
3333                                                                                                          
3334         private final Collator mCollator;                                                                
3335                                                                                                          
3336         WidgetAndShortcutNameComparator(Context context) {                                               
3337             mManager = AppWidgetManagerCompat.getInstance(context);                                      
3338             mPackageManager = context.getPackageManager();                                               
3339             mLabelCache = new HashMap<Object, String>();                                                 
3340             mCollator = Collator.getInstance();                                                          
3341         }                                                                                                
3342                                                                                                          
3343         public final int compare(Object a, Object b) {                                                   
3344             String labelA;                                                                               
3345             String labelB;                                                                               
3346             if (mLabelCache.containsKey(a)) {                                                            
3347                 labelA = mLabelCache.get(a);                                                             
3348             } else {                                                                                     
3349                 labelA = (a instanceof AppWidgetProviderInfo) ? mManager.loadLabel(((AppWidgetProviderInf🔵
3350                 mLabelCache.put(a, labelA);                                                              
3351             }                                                                                            
3352             if (mLabelCache.containsKey(b)) {                                                            
3353                 labelB = mLabelCache.get(b);                                                             
3354             } else {                                                                                     
3355                 labelB = (b instanceof AppWidgetProviderInfo) ? mManager.loadLabel(((AppWidgetProviderInf🔵
3356                 mLabelCache.put(b, labelB);                                                              
3357             }                                                                                            
3358             return mCollator.compare(labelA, labelB);                                                    
3359         }                                                                                                
3360     }                                                                                                    
3361                                                                                                          
3362     static boolean isValidProvider(AppWidgetProviderInfo provider) {                                     
3363         return ((provider != null) && (provider.provider != null)) && (provider.provider.getPackageName()🔵
3364     }                                                                                                    
3365                                                                                                          
3366     public void dumpState() {                                                                            
3367         Log.d(TAG, "mCallbacks=" + mCallbacks);                                                          
3368         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);                  
3369         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);                
3370         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);            
3371         AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);          
3372         if (mLoaderTask != null) {                                                                       
3373             mLoaderTask.dumpState();                                                                     
3374         } else {                                                                                         
3375             Log.d(TAG, "mLoaderTask=null");                                                              
3376         }                                                                                                
3377     }                                                                                                    
3378 }                                                                                                        






























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































ours vs. base theirs vs. base
   1  /*                                                                                                                
   2   * Copyright (C) 2008 The Android Open Source Project                                                             
   3   *                                                                                                                
   4   * Licensed under the Apache License, Version 2.0 (the "License");                                                
   5   * you may not use this file except in compliance with the License.                                               
   6   * You may obtain a copy of the License at                                                                        
   7   *                                                                                                                
   8   *      http://www.apache.org/licenses/LICENSE-2.0                                                                
   9   *                                                                                                                
  10   * Unless required by applicable law or agreed to in writing, software                                            
  11   * distributed under the License is distributed on an "AS IS" BASIS,                                              
  12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.                                       
  13   * See the License for the specific language governing permissions and                                            
  14   * limitations under the License.                                                                                 
  15   */                                                                                                               
  16                                                                                                                    
  17  package com.android.launcher3;                                                                                    
  18                                                                                                                    
  19  import android.app.SearchManager;                                                                                 
  20  import android.appwidget.AppWidgetManager;                                                                        
  21  import android.appwidget.AppWidgetProviderInfo;                                                                   
  22 -import android.content.*;                                                                                         
  23 +import android.content.BroadcastReceiver;                                                                         
  24 +import android.content.ComponentName;                                                                             
  25 +import android.content.ContentProviderClient;                                                                     
  26 +import android.content.ContentProviderOperation;                                                                  
  27 +import android.content.ContentResolver;                                                                           
  28 +import android.content.ContentValues;                                                                             
  29 +import android.content.Context;                                                                                   
  30 +import android.content.Intent;                                                                                    
  31  import android.content.Intent.ShortcutIconResource;                                                               
  32 -import android.content.pm.ActivityInfo;                                                                           
  33 -import android.content.pm.PackageInfo;                                                                            
  34 +import android.content.IntentFilter;                                                                              
  35 +import android.content.SharedPreferences;                                                                         
  36  import android.content.pm.PackageManager;                                                                         
  37 -import android.content.pm.PackageManager.NameNotFoundException;                                                   
  38 +import android.content.pm.ProviderInfo;                                                                           
  39  import android.content.pm.ResolveInfo;                                                                            
  40  import android.content.res.Configuration;                                                                         
  41  import android.content.res.Resources;                                                                             
  42  import android.database.Cursor;                                                                                   
  43  import android.graphics.Bitmap;                                                                                   
  44  import android.graphics.BitmapFactory;                                                                            
  45  import android.net.Uri;                                                                                           
  46  import android.os.Environment;                                                                                    
  47  import android.os.Handler;                                                                                        
  48  import android.os.HandlerThread;                                                                                  
  49  import android.os.Parcelable;                                                                                     
  50  import android.os.Process;                                                                                        
  51  import android.os.RemoteException;                                                                                
  52  import android.os.SystemClock;                                                                                    
  53  import android.provider.BaseColumns;                                                                              
  54  import android.text.TextUtils;                                                                                    
  55  import android.util.Log;                                                                                          
  56  import android.util.Pair;                                                                                         
  57                                                                                                                    
  58 -import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;                                     
  59 +import com.android.launcher3.compat.AppWidgetManagerCompat;                                                       
  60 +import com.android.launcher3.compat.LauncherActivityInfoCompat;                                                   
  61 +import com.android.launcher3.compat.LauncherAppsCompat;                                                           
  62 +import com.android.launcher3.compat.PackageInstallerCompat;                                                       
  63 +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;                                    
  64 +import com.android.launcher3.compat.UserHandleCompat;                                                             
  65 +import com.android.launcher3.compat.UserManagerCompat;                                                            
  66                                                                                                                    
  67  import java.lang.ref.WeakReference;                                                                               
  68  import java.net.URISyntaxException;                                                                               
  69 +import java.security.InvalidParameterException;                                                                   
  70  import java.text.Collator;                                                                                        
  71  import java.util.ArrayList;                                                                                       
  72  import java.util.Arrays;                                                                                          
  73  import java.util.Collection;                                                                                      
  74  import java.util.Collections;                                                                                     
  75  import java.util.Comparator;                                                                                      
  76  import java.util.HashMap;                                                                                         
  77  import java.util.HashSet;                                                                                         
  78  import java.util.Iterator;                                                                                        
  79  import java.util.List;                                                                                            
  80 +import java.util.Map.Entry;                                                                                       
  81  import java.util.Set;                                                                                             
  82  import java.util.TreeMap;                                                                                         
  83  import java.util.concurrent.atomic.AtomicBoolean;                                                                 
  84                                                                                                                    
  85  /**                                                                                                               
  86   * Maintains in-memory state of the Launcher. It is expected that there should be only one                        
  87   * LauncherModel object held in a static. Also provide APIs for updating the database state                       
  88   * for the Launcher.                                                                                              
  89   */                                                                                                               
  90 -public class LauncherModel extends BroadcastReceiver {                                                            
  91 +public class LauncherModel extends BroadcastReceiver                                                              
  92 +        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {                                               
  93      static final boolean DEBUG_LOADERS = false;                                                                   
  94 +    private static final boolean DEBUG_RECEIVER = false;                                                          
  95 +    private static final boolean REMOVE_UNRESTORED_ICONS = true;                                                  
  96 +                                                                                                                  
  97      static final String TAG = "Launcher.Model";                                                                   
  98                                                                                                                    
  99      // true = use a "More Apps" folder for non-workspace apps on upgrade                                          
 100      // false = strew non-workspace apps across the workspace on upgrade                                           
 101      public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;                                             
 102 -                                                                                                                  
 103      public static final int LOADER_FLAG_NONE = 0;                                                                 
 104      public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;                                                 
 105      public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;                                               
 106                                                                                                                    
 107      private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons                               
 108      private static final long INVALID_SCREEN_ID = -1L;                                                            
 109                                                                                                                    
 110      private final boolean mAppsCanBeOnRemoveableStorage;                                                          
 111      private final boolean mOldContentProviderExists;                                                              
 112                                                                                                                    
 113      private final LauncherAppState mApp;                                                                          
 114      private final Object mLock = new Object();                                                                    
 115      private DeferredHandler mHandler = new DeferredHandler();                                                     
 116      private LoaderTask mLoaderTask;                                                                               
 117      private boolean mIsLoaderTaskRunning;                                                                         
 118      private volatile boolean mFlushingWorkerThread;                                                               
 119                                                                                                                    
 120      // Specific runnable types that are run on the main thread deferred handler, this allows us to                
 121      // clear all queued binding runnables when the Launcher activity is destroyed.                                
 122      private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;                                                     
 123      private static final int MAIN_THREAD_BINDING_RUNNABLE = 1;                                                    
 124                                                                                                                    
 125 +    private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";                             
 126                                                                                                                    
 127      private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");                      
 128      static {                                                                                                      
 129          sWorkerThread.start();                                                                                    
 130      }                                                                                                             
 131      private static final Handler sWorker = new Handler(sWorkerThread.getLooper());                                
 132                                                                                                                    
 133      // We start off with everything not loaded.  After that, we assume that                                       
 134      // our monitoring of the package manager provides all updates and we never                                    
 135      // need to do a requery.  These are only ever touched from the loader thread.                                 
 136      private boolean mWorkspaceLoaded;                                                                             
 137      private boolean mAllAppsLoaded;                                                                               
 138                                                                                                                    
 139      // When we are loading pages synchronously, we can't just post the binding of items on the side               
 140      // pages as this delays the rotation process.  Instead, we wait for a callback from the first                 
 141      // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start                
 142      // a normal load, we also clear this set of Runnables.                                                        
 143      static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();                          
 144                                                                                                                    
 145      private WeakReference<Callbacks> mCallbacks;                                                                  
 146                                                                                                                    
 147      // < only access in worker thread >                                                                           
 148      AllAppsList mBgAllAppsList;                                                                                   
 149                                                                                                                    
 150      // The lock that must be acquired before referencing any static bg data structures.  Unlike                   
 151      // other locks, this one can generally be held long-term because we never expect any of these                 
 152      // static data structures to be referenced outside of the worker thread except on the first                   
 153      // load after configuration change.                                                                           
 154      static final Object sBgLock = new Object();                                                                   
 155                                                                                                                    
 156      // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by                        
 157      // LauncherModel to their ids                                                                                 
 158      static final HashMap<Long, ItemInfo> sBgItemsIdMap = new HashMap<Long, ItemInfo>();                           
 159                                                                                                                    
 160      // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts                
 161      //       created by LauncherModel that are directly on the home screen (however, no widgets or                
 162      //       shortcuts within folders).                                                                           
 163      static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();                               
 164                                                                                                                    
 165      // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()             
 166      static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =                                                 
 167          new ArrayList<LauncherAppWidgetInfo>();                                                                   
 168                                                                                                                    
 169      // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()                            
 170      static final HashMap<Long, FolderInfo> sBgFolders = new HashMap<Long, FolderInfo>();                          
 171                                                                                                                    
 172      // sBgDbIconCache is the set of ItemInfos that need to have their icons updated in the database               
 173      static final HashMap<Object, byte[]> sBgDbIconCache = new HashMap<Object, byte[]>();                          
 174                                                                                                                    
 175      // sBgWorkspaceScreens is the ordered set of workspace screens.                                               
 176      static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();                                     
 177                                                                                                                    
 178 +    // sPendingPackages is a set of packages which could be on sdcard and are not available yet                   
 179 +    static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =                                    
 180 +            new HashMap<UserHandleCompat, HashSet<String>>();                                                     
 181 +                                                                                                                  
 182      // </ only access in worker thread >                                                                          
 183                                                                                                                    
 184      private IconCache mIconCache;                                                                                 
 185 -    private Bitmap mDefaultIcon;                                                                                  
 186                                                                                                                    
 187      protected int mPreviousConfigMcc;                                                                             
 188 +                                                                                                                  
 189 +    private final LauncherAppsCompat mLauncherApps;                                                               
 190 +    private final UserManagerCompat mUserManager;                                                                 
 191                                                                                                                    
 192      public interface Callbacks {                                                                                  
 193          public boolean setLoadOnResume();                                                                         
 194          public int getCurrentWorkspaceScreen();                                                                   
 195          public void startBinding();                                                                               
 196          public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,                                  
 197                                boolean forceAnimateIcons);                                                         
 198          public void bindScreens(ArrayList<Long> orderedScreenIds);                                                
 199          public void bindAddScreens(ArrayList<Long> orderedScreenIds);                                             
 200          public void bindFolders(HashMap<Long,FolderInfo> folders);                                                
 201          public void finishBindingItems(boolean upgradePath);                                                      
 202          public void bindAppWidget(LauncherAppWidgetInfo info);                                                    
 203          public void bindAllApplications(ArrayList<AppInfo> apps);                                                 
 204          public void bindAppsAdded(ArrayList<Long> newScreens,                                                     
 205                                    ArrayList<ItemInfo> addNotAnimated,                                             
 206                                    ArrayList<ItemInfo> addAnimated,                                                
 207                                    ArrayList<AppInfo> addedApps);                                                  
 208          public void bindAppsUpdated(ArrayList<AppInfo> apps);                                                     
 209 +        public void bindAppsRestored(ArrayList<AppInfo> apps);                                                    
 210 +        public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);                                
 211 +        public void updatePackageBadge(String packageName);                                                       
 212          public void bindComponentsRemoved(ArrayList<String> packageNames,                                         
 213 -                        ArrayList<AppInfo> appInfos);                                                             
 214 +                        ArrayList<AppInfo> appInfos, UserHandleCompat user);                                      
 215          public void bindPackagesUpdated(ArrayList<Object> widgetsAndShortcuts);                                   
 216          public void bindSearchablesChanged();                                                                     
 217          public boolean isAllAppsButtonRank(int rank);                                                             
 218          public void onPageBoundSynchronously(int page);                                                           
 219          public void dumpLogsToLocalData();                                                                        
 220      }                                                                                                             
 221                                                                                                                    
 222      public interface ItemInfoFilter {                                                                             
 223          public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);                              
 224      }                                                                                                             
 225                                                                                                                    
 226      LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {                               
 227          Context context = app.getContext();                                                                       
 228 -        ContentResolver contentResolver = context.getContentResolver();                                           
 229                                                                                                                    
 230          mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();                                 
 231 -        mOldContentProviderExists = (contentResolver.acquireContentProviderClient(                                
 232 -                LauncherSettings.Favorites.OLD_CONTENT_URI) != null);                                             
 233 +        String oldProvider = context.getString(R.string.old_launcher_provider_uri);                               
 234 +        // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different                        
 235 +        // resource string.                                                                                       
 236 +        String redirectAuthority = Uri.parse(oldProvider).getAuthority();                                         
 237 +        ProviderInfo providerInfo =                                                                               
 238 +                context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY, 0);                         
 239 +        ProviderInfo redirectProvider =                                                                           
 240 +                context.getPackageManager().resolveContentProvider(redirectAuthority, 0);                         
 241 +                                                                                                                  
 242 +        Log.d(TAG, "Old launcher provider: " + oldProvider);                                                      
 243 +        mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);                         
 244 +                                                                                                                  
 245 +        if (mOldContentProviderExists) {                                                                          
 246 +            Log.d(TAG, "Old launcher provider exists.");                                                          
 247 +        } else {                                                                                                  
 248 +            Log.d(TAG, "Old launcher provider does not exist.");                                                  
 249 +        }                                                                                                         
 250 +                                                                                                                  
 251          mApp = app;                                                                                               
 252          mBgAllAppsList = new AllAppsList(iconCache, appFilter);                                                   
 253          mIconCache = iconCache;                                                                                   
 254                                                                                                                    
 255          final Resources res = context.getResources();                                                             
 256          Configuration config = res.getConfiguration();                                                            
 257          mPreviousConfigMcc = config.mcc;                                                                          
 258 +        mLauncherApps = LauncherAppsCompat.getInstance(context);                                                  
 259 +        mUserManager = UserManagerCompat.getInstance(context);                                                    
 260      }                                                                                                             
 261                                                                                                                    
 262      /** Runs the specified runnable immediately if called from the main thread, otherwise it is                   
 263       * posted on the main thread handler. */                                                                      
 264      private void runOnMainThread(Runnable r) {                                                                    
 265          runOnMainThread(r, 0);                                                                                    
 266      }                                                                                                             
 267      private void runOnMainThread(Runnable r, int type) {                                                          
 268          if (sWorkerThread.getThreadId() == Process.myTid()) {                                                     
 269              // If we are on the worker thread, post onto the main handler                                         
 270              mHandler.post(r);                                                                                     
 271          } else {                                                                                                  
 272              r.run();                                                                                              
 273          }                                                                                                         
 274      }                                                                                                             
 275                                                                                                                    
 276      /** Runs the specified runnable immediately if called from the worker thread, otherwise it is                 
 277       * posted on the worker thread handler. */                                                                    
 278      private static void runOnWorkerThread(Runnable r) {                                                           
 279          if (sWorkerThread.getThreadId() == Process.myTid()) {                                                     
 280              r.run();                                                                                              
 281          } else {                                                                                                  
 282              // If we are not on the worker thread, then post to the worker handler                                
 283              sWorker.post(r);                                                                                      
 284          }                                                                                                         
 285      }                                                                                                             
 286                                                                                                                    
 287      boolean canMigrateFromOldLauncherDb(Launcher launcher) {                                                      
 288          return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;                                  
 289      }                                                                                                             
 290                                                                                                                    
 291      static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,                        
 292                                   long screen) {                                                                   
 293          LauncherAppState app = LauncherAppState.getInstance();                                                    
 294          DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                             
 295          final int xCount = (int) grid.numColumns;                                                                 
 296          final int yCount = (int) grid.numRows;                                                                    
 297          boolean[][] occupied = new boolean[xCount][yCount];                                                       
 298                                                                                                                    
 299          int cellX, cellY, spanX, spanY;                                                                           
 300          for (int i = 0; i < items.size(); ++i) {                                                                  
 301              final ItemInfo item = items.get(i);                                                                   
 302              if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                                 
 303                  if (item.screenId == screen) {                                                                    
 304                      cellX = item.cellX;                                                                           
 305                      cellY = item.cellY;                                                                           
 306                      spanX = item.spanX;                                                                           
 307                      spanY = item.spanY;                                                                           
 308                      for (int x = cellX; 0 <= x && x < cellX + spanX && x < xCount; x++) {                         
 309                          for (int y = cellY; 0 <= y && y < cellY + spanY && y < yCount; y++) {                     
 310                              occupied[x][y] = true;                                                                
 311                          }                                                                                         
 312                      }                                                                                             
 313                  }                                                                                                 
 314              }                                                                                                     
 315          }                                                                                                         
 316                                                                                                                    
 317          return CellLayout.findVacantCell(xy, 1, 1, xCount, yCount, occupied);                                     
 318      }                                                                                                             
 319      static Pair<Long, int[]> findNextAvailableIconSpace(Context context, String name,                             
 320                                                          Intent launchIntent,                                      
 321                                                          int firstScreenIndex,                                     
 322                                                          ArrayList<Long> workspaceScreens) {                       
 323          // Lock on the app so that we don't try and get the items while apps are being added                      
 324          LauncherAppState app = LauncherAppState.getInstance();                                                    
 325          LauncherModel model = app.getModel();                                                                     
 326          boolean found = false;                                                                                    
 327          synchronized (app) {                                                                                      
 328              if (sWorkerThread.getThreadId() != Process.myTid()) {                                                 
 329                  // Flush the LauncherModel worker thread, so that if we just did another                          
 330                  // processInstallShortcut, we give it time for its shortcut to get added to the                   
 331                  // database (getItemsInLocalCoordinates reads the database)                                       
 332                  model.flushWorkerThread();                                                                        
 333              }                                                                                                     
 334              final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);                  
 335                                                                                                                    
 336              // Try adding to the workspace screens incrementally, starting at the default or center               
 337              // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))                
 338              firstScreenIndex = Math.min(firstScreenIndex, workspaceScreens.size());                               
 339              int count = workspaceScreens.size();                                                                  
 340              for (int screen = firstScreenIndex; screen < count && !found; screen++) {                             
 341                  int[] tmpCoordinates = new int[2];                                                                
 342                  if (findNextAvailableIconSpaceInScreen(items, tmpCoordinates,                                     
 343                          workspaceScreens.get(screen))) {                                                          
 344                      // Update the Launcher db                                                                     
 345                      return new Pair<Long, int[]>(workspaceScreens.get(screen), tmpCoordinates);                   
 346                  }                                                                                                 
 347              }                                                                                                     
 348          }                                                                                                         
 349          return null;                                                                                              
 350      }                                                                                                             
 351                                                                                                                    
 352 -    public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,               
 353 -                                    final ArrayList<AppInfo> allAppsApps) {                                       
 354 -        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                              
 355 -        addAndBindAddedApps(context, workspaceApps, cb, allAppsApps);                                             
 356 -    }                                                                                                             
 357 -    public void addAndBindAddedApps(final Context context, final ArrayList<ItemInfo> workspaceApps,               
 358 -                                final Callbacks callbacks, final ArrayList<AppInfo> allAppsApps) {                
 359 -        if (workspaceApps == null || allAppsApps == null) {                                                       
 360 +    public void setPackageState(final ArrayList<PackageInstallInfo> installInfo) {                                
 361 +        // Process the updated package state                                                                      
 362 +        Runnable r = new Runnable() {                                                                             
 363 +            public void run() {                                                                                   
 364 +                Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                               
 365 +                if (callbacks != null) {                                                                          
 366 +                    callbacks.updatePackageState(installInfo);                                                    
 367 +                }                                                                                                 
 368 +            }                                                                                                     
 369 +        };                                                                                                        
 370 +        mHandler.post(r);                                                                                         
 371 +    }                                                                                                             
 372 +                                                                                                                  
 373 +    public void updatePackageBadge(final String packageName) {                                                    
 374 +        // Process the updated package badge                                                                      
 375 +        Runnable r = new Runnable() {                                                                             
 376 +            public void run() {                                                                                   
 377 +                Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                               
 378 +                if (callbacks != null) {                                                                          
 379 +                    callbacks.updatePackageBadge(packageName);                                                    
 380 +                }                                                                                                 
 381 +            }                                                                                                     
 382 +        };                                                                                                        
 383 +        mHandler.post(r);                                                                                         
 384 +    }                                                                                                             
 385 +                                                                                                                  
 386 +    public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {                       
 387 +        final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                                 
 388 +                                                                                                                  
 389 +        if (allAppsApps == null) {                                                                                
 390 +            throw new RuntimeException("allAppsApps must not be null");                                           
 391 +        }                                                                                                         
 392 +        if (allAppsApps.isEmpty()) {                                                                              
 393 +            return;                                                                                               
 394 +        }                                                                                                         
 395 +                                                                                                                  
 396 +        final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                                    
 397 +        Iterator<AppInfo> iter = allAppsApps.iterator();                                                          
 398 +        while (iter.hasNext()) {                                                                                  
 399 +            ItemInfo a = iter.next();                                                                             
 400 +            if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {                                        
 401 +                restoredAppsFinal.add((AppInfo) a);                                                               
 402 +            }                                                                                                     
 403 +        }                                                                                                         
 404 +                                                                                                                  
 405 +        // Process the newly added applications and add them to the database first                                
 406 +        Runnable r = new Runnable() {                                                                             
 407 +            public void run() {                                                                                   
 408 +                runOnMainThread(new Runnable() {                                                                  
 409 +                    public void run() {                                                                           
 410 +                        Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                              
 411 +                        if (callbacks == cb && cb != null) {                                                      
 412 +                            if (!restoredAppsFinal.isEmpty()) {                                                   
 413 +                                for (AppInfo info : restoredAppsFinal) {                                          
 414 +                                    final Intent intent = info.getIntent();                                       
 415 +                                    if (intent != null) {                                                         
 416 +                                        mIconCache.deletePreloadedIcon(intent.getComponent(),                     
 417 +                                                info.user);                                                       
 418 +                                    }                                                                             
 419 +                                }                                                                                 
 420 +                                callbacks.bindAppsUpdated(restoredAppsFinal);                                     
 421 +                            }                                                                                     
 422 +                            callbacks.bindAppsAdded(null, null, null, allAppsApps);                               
 423 +                        }                                                                                         
 424 +                    }                                                                                             
 425 +                });                                                                                               
 426 +            }                                                                                                     
 427 +        };                                                                                                        
 428 +        runOnWorkerThread(r);                                                                                     
 429 +    }                                                                                                             
 430 +                                                                                                                  
 431 +    public void addAndBindAddedWorkspaceApps(final Context context,                                               
 432 +            final ArrayList<ItemInfo> workspaceApps) {                                                            
 433 +        final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                                 
 434 +                                                                                                                  
 435 +        if (workspaceApps == null) {                                                                              
 436              throw new RuntimeException("workspaceApps and allAppsApps must not be null");                         
 437          }                                                                                                         
 438 -        if (workspaceApps.isEmpty() && allAppsApps.isEmpty()) {                                                   
 439 +        if (workspaceApps.isEmpty()) {                                                                            
 440              return;                                                                                               
 441          }                                                                                                         
 442          // Process the newly added applications and add them to the database first                                
 443          Runnable r = new Runnable() {                                                                             
 444              public void run() {                                                                                   
 445                  final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();                        
 446                  final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();                         
 447 +                final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();                            
 448                                                                                                                    
 449                  // Get the list of workspace screens.  We need to append to this list and                         
 450                  // can not use sBgWorkspaceScreens because loadWorkspace() may not have been                      
 451                  // called.                                                                                        
 452                  ArrayList<Long> workspaceScreens = new ArrayList<Long>();                                         
 453                  TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(context);                          
 454                  for (Integer i : orderedScreens.keySet()) {                                                       
 455                      long screenId = orderedScreens.get(i);                                                        
 456                      workspaceScreens.add(screenId);                                                               
 457                  }                                                                                                 
 458                                                                                                                    
 459                  synchronized(sBgLock) {                                                                           
 460                      Iterator<ItemInfo> iter = workspaceApps.iterator();                                           
 461                      while (iter.hasNext()) {                                                                      
 462                          ItemInfo a = iter.next();                                                                 
 463                          final String name = a.title.toString();                                                   
 464                          final Intent launchIntent = a.getIntent();                                                
 465                                                                                                                    
 466                          // Short-circuit this logic if the icon exists somewhere on the workspace                 
 467                          if (LauncherModel.shortcutExists(context, name, launchIntent)) {                          
 468 +                            // Only InstallShortcutReceiver sends us shortcutInfos, ignore them                   
 469 +                            if (a instanceof AppInfo &&                                                           
 470 +                                    LauncherModel.appWasPromise(context, launchIntent, a.user)) {                 
 471 +                                restoredAppsFinal.add((AppInfo) a);                                               
 472 +                            }                                                                                     
 473                              continue;                                                                             
 474                          }                                                                                         
 475                                                                                                                    
 476                          // Add this icon to the db, creating a new page if necessary.  If there                   
 477                          // is only the empty page then we just add items to the first page.                       
 478                          // Otherwise, we add them to the next pages.                                              
 479                          int startSearchPageIndex = workspaceScreens.isEmpty() ? 0 : 1;                            
 480                          Pair<Long, int[]> coords = LauncherModel.findNextAvailableIconSpace(context,              
 481                                  name, launchIntent, startSearchPageIndex, workspaceScreens);                      
 482                          if (coords == null) {                                                                     
 483                              LauncherProvider lp = LauncherAppState.getLauncherProvider();                         
 484                                                                                                                    
 485                              // If we can't find a valid position, then just add a new screen.                     
 486                              // This takes time so we need to re-queue the add until the new                       
 487                              // page is added.  Create as many screens as necessary to satisfy                     
 488                              // the startSearchPageIndex.                                                          
 489                              int numPagesToAdd = Math.max(1, startSearchPageIndex + 1 -                            
 490                                      workspaceScreens.size());                                                     
 491                              while (numPagesToAdd > 0) {                                                           
 492                                  long screenId = lp.generateNewScreenId();                                         
 493                                  // Save the screen id for binding in the workspace                                
 494                                  workspaceScreens.add(screenId);                                                   
 495                                  addedWorkspaceScreensFinal.add(screenId);                                         
 496                                  numPagesToAdd--;                                                                  
 497                              }                                                                                     
 498                                                                                                                    
 499                              // Find the coordinate again                                                          
 500                              coords = LauncherModel.findNextAvailableIconSpace(context,                            
 501                                      name, launchIntent, startSearchPageIndex, workspaceScreens);                  
 502                          }                                                                                         
 503                          if (coords == null) {                                                                     
 504                              throw new RuntimeException("Coordinates should not be null");                         
 505                          }                                                                                         
 506                                                                                                                    
 507                          ShortcutInfo shortcutInfo;                                                                
 508                          if (a instanceof ShortcutInfo) {                                                          
 509                              shortcutInfo = (ShortcutInfo) a;                                                      
 510                          } else if (a instanceof AppInfo) {                                                        
 511                              shortcutInfo = ((AppInfo) a).makeShortcut();                                          
 512                          } else {                                                                                  
 513                              throw new RuntimeException("Unexpected info type");                                   
 514                          }                                                                                         
 515                                                                                                                    
 516                          // Add the shortcut to the db                                                             
 517                          addItemToDatabase(context, shortcutInfo,                                                  
 518                                  LauncherSettings.Favorites.CONTAINER_DESKTOP,                                     
 519                                  coords.first, coords.second[0], coords.second[1], false);                         
 520                          // Save the ShortcutInfo for binding in the workspace                                     
 521                          addedShortcutsFinal.add(shortcutInfo);                                                    
 522                      }                                                                                             
 523                  }                                                                                                 
 524                                                                                                                    
 525                  // Update the workspace screens                                                                   
 526                  updateWorkspaceScreenOrder(context, workspaceScreens);                                            
 527                                                                                                                    
 528 -                if (!addedShortcutsFinal.isEmpty() || !allAppsApps.isEmpty()) {                                   
 529 +                if (!addedShortcutsFinal.isEmpty()) {                                                             
 530                      runOnMainThread(new Runnable() {                                                              
 531                          public void run() {                                                                       
 532                              Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                          
 533                              if (callbacks == cb && cb != null) {                                                  
 534                                  final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();                
 535                                  final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();             
 536                                  if (!addedShortcutsFinal.isEmpty()) {                                             
 537                                      ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 1);      
 538                                      long lastScreenId = info.screenId;                                            
 539                                      for (ItemInfo i : addedShortcutsFinal) {                                      
 540                                          if (i.screenId == lastScreenId) {                                         
 541                                              addAnimated.add(i);                                                   
 542                                          } else {                                                                  
 543                                              addNotAnimated.add(i);                                                
 544                                          }                                                                         
 545                                      }                                                                             
 546                                  }                                                                                 
 547                                  callbacks.bindAppsAdded(addedWorkspaceScreensFinal,                               
 548 -                                        addNotAnimated, addAnimated, allAppsApps);                                
 549 +                                        addNotAnimated, addAnimated, null);                                       
 550 +                                if (!restoredAppsFinal.isEmpty()) {                                               
 551 +                                    callbacks.bindAppsUpdated(restoredAppsFinal);                                 
 552 +                                }                                                                                 
 553                              }                                                                                     
 554                          }                                                                                         
 555                      });                                                                                           
 556                  }                                                                                                 
 557              }                                                                                                     
 558          };                                                                                                        
 559          runOnWorkerThread(r);                                                                                     
 560 -    }                                                                                                             
 561 -                                                                                                                  
 562 -    public Bitmap getFallbackIcon() {                                                                             
 563 -        if (mDefaultIcon == null) {                                                                               
 564 -            final Context context = LauncherAppState.getInstance().getContext();                                  
 565 -            mDefaultIcon = Utilities.createIconBitmap(                                                            
 566 -                    mIconCache.getFullResDefaultActivityIcon(), context);                                         
 567 -        }                                                                                                         
 568 -        return Bitmap.createBitmap(mDefaultIcon);                                                                 
 569      }                                                                                                             
 570                                                                                                                    
 571      public void unbindItemInfosAndClearQueuedBindRunnables() {                                                    
 572          if (sWorkerThread.getThreadId() == Process.myTid()) {                                                     
 573              throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +              
 574                      "main thread");                                                                               
 575          }                                                                                                         
 576                                                                                                                    
 577          // Clear any deferred bind runnables                                                                      
 578 -        mDeferredBindRunnables.clear();                                                                           
 579 +        synchronized (mDeferredBindRunnables) {                                                                   
 580 +            mDeferredBindRunnables.clear();                                                                       
 581 +        }                                                                                                         
 582          // Remove any queued bind runnables                                                                       
 583          mHandler.cancelAllRunnablesOfType(MAIN_THREAD_BINDING_RUNNABLE);                                          
 584          // Unbind all the workspace items                                                                         
 585          unbindWorkspaceItemsOnMainThread();                                                                       
 586      }                                                                                                             
 587                                                                                                                    
 588      /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */                                 
 589      void unbindWorkspaceItemsOnMainThread() {                                                                     
 590          // Ensure that we don't use the same workspace items data structure on the main thread                    
 591          // by making a copy of workspace items first.                                                             
 592          final ArrayList<ItemInfo> tmpWorkspaceItems = new ArrayList<ItemInfo>();                                  
 593          final ArrayList<ItemInfo> tmpAppWidgets = new ArrayList<ItemInfo>();                                      
 594          synchronized (sBgLock) {                                                                                  
 595              tmpWorkspaceItems.addAll(sBgWorkspaceItems);                                                          
 596              tmpAppWidgets.addAll(sBgAppWidgets);                                                                  
 597          }                                                                                                         
 598          Runnable r = new Runnable() {                                                                             
 599                  @Override                                                                                         
 600                  public void run() {                                                                               
 601                     for (ItemInfo item : tmpWorkspaceItems) {                                                      
 602                         item.unbind();                                                                             
 603                     }                                                                                              
 604                     for (ItemInfo item : tmpAppWidgets) {                                                          
 605                         item.unbind();                                                                             
 606                     }                                                                                              
 607                  }                                                                                                 
 608              };                                                                                                    
 609          runOnMainThread(r);                                                                                       
 610      }                                                                                                             
 611                                                                                                                    
 612      /**                                                                                                           
 613       * Adds an item to the DB if it was not created previously, or move it to a new                               
 614       * <container, screen, cellX, cellY>                                                                          
 615       */                                                                                                           
 616      static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,                           
 617              long screenId, int cellX, int cellY) {                                                                
 618          if (item.container == ItemInfo.NO_ID) {                                                                   
 619              // From all apps                                                                                      
 620              addItemToDatabase(context, item, container, screenId, cellX, cellY, false);                           
 621          } else {                                                                                                  
 622              // From somewhere else                                                                                
 623              moveItemInDatabase(context, item, container, screenId, cellX, cellY);                                 
 624          }                                                                                                         
 625      }                                                                                                             
 626                                                                                                                    
 627      static void checkItemInfoLocked(                                                                              
 628              final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {                             
 629          ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                                           
 630          if (modelItem != null && item != modelItem) {                                                             
 631              // check all the data is consistent                                                                   
 632              if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {                              
 633                  ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;                                            
 634                  ShortcutInfo shortcut = (ShortcutInfo) item;                                                      
 635                  if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&                           
 636                          modelShortcut.intent.filterEquals(shortcut.intent) &&                                     
 637                          modelShortcut.id == shortcut.id &&                                                        
 638                          modelShortcut.itemType == shortcut.itemType &&                                            
 639                          modelShortcut.container == shortcut.container &&                                          
 640                          modelShortcut.screenId == shortcut.screenId &&                                            
 641                          modelShortcut.cellX == shortcut.cellX &&                                                  
 642                          modelShortcut.cellY == shortcut.cellY &&                                                  
 643                          modelShortcut.spanX == shortcut.spanX &&                                                  
 644                          modelShortcut.spanY == shortcut.spanY &&                                                  
 645                          ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||                           
 646                          (modelShortcut.dropPos != null &&                                                         
 647                                  shortcut.dropPos != null &&                                                       
 648                                  modelShortcut.dropPos[0] == shortcut.dropPos[0] &&                                
 649                          modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {                                      
 650                      // For all intents and purposes, this is the same object                                      
 651                      return;                                                                                       
 652                  }                                                                                                 
 653              }                                                                                                     
 654                                                                                                                    
 655              // the modelItem needs to match up perfectly with item if our model is                                
 656              // to be consistent with the database-- for now, just require                                         
 657              // modelItem == item or the equality check above                                                      
 658              String msg = "item: " + ((item != null) ? item.toString() : "null") +                                 
 659                      "modelItem: " +                                                                               
 660                      ((modelItem != null) ? modelItem.toString() : "null") +                                       
 661                      "Error: ItemInfo passed to checkItemInfo doesn't match original";                             
 662              RuntimeException e = new RuntimeException(msg);                                                       
 663              if (stackTrace != null) {                                                                             
 664                  e.setStackTrace(stackTrace);                                                                      
 665              }                                                                                                     
 666              throw e;                                                                                              
 667          }                                                                                                         
 668      }                                                                                                             
 669                                                                                                                    
 670      static void checkItemInfo(final ItemInfo item) {                                                              
 671          final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                                   
 672          final long itemId = item.id;                                                                              
 673          Runnable r = new Runnable() {                                                                             
 674              public void run() {                                                                                   
 675                  synchronized (sBgLock) {                                                                          
 676                      checkItemInfoLocked(itemId, item, stackTrace);                                                
 677                  }                                                                                                 
 678              }                                                                                                     
 679          };                                                                                                        
 680          runOnWorkerThread(r);                                                                                     
 681      }                                                                                                             
 682                                                                                                                    
 683      static void updateItemInDatabaseHelper(Context context, final ContentValues values,                           
 684              final ItemInfo item, final String callingFunction) {                                                  
 685          final long itemId = item.id;                                                                              
 686          final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);                                  
 687          final ContentResolver cr = context.getContentResolver();                                                  
 688                                                                                                                    
 689          final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                                   
 690          Runnable r = new Runnable() {                                                                             
 691              public void run() {                                                                                   
 692                  cr.update(uri, values, null, null);                                                               
 693                  updateItemArrays(item, itemId, stackTrace);                                                       
 694              }                                                                                                     
 695          };                                                                                                        
 696          runOnWorkerThread(r);                                                                                     
 697      }                                                                                                             
 698                                                                                                                    
 699      static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,           
 700              final ArrayList<ItemInfo> items, final String callingFunction) {                                      
 701          final ContentResolver cr = context.getContentResolver();                                                  
 702                                                                                                                    
 703          final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                                   
 704          Runnable r = new Runnable() {                                                                             
 705              public void run() {                                                                                   
 706                  ArrayList<ContentProviderOperation> ops =                                                         
 707                          new ArrayList<ContentProviderOperation>();                                                
 708                  int count = items.size();                                                                         
 709                  for (int i = 0; i < count; i++) {                                                                 
 710                      ItemInfo item = items.get(i);                                                                 
 711                      final long itemId = item.id;                                                                  
 712                      final Uri uri = LauncherSettings.Favorites.getContentUri(itemId, false);                      
 713                      ContentValues values = valuesList.get(i);                                                     
 714                                                                                                                    
 715                      ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());                  
 716                      updateItemArrays(item, itemId, stackTrace);                                                   
 717                                                                                                                    
 718                  }                                                                                                 
 719                  try {                                                                                             
 720                      cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                               
 721                  } catch (Exception e) {                                                                           
 722                      e.printStackTrace();                                                                          
 723                  }                                                                                                 
 724              }                                                                                                     
 725          };                                                                                                        
 726          runOnWorkerThread(r);                                                                                     
 727      }                                                                                                             
 728                                                                                                                    
 729      static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {                    
 730          // Lock on mBgLock *after* the db operation                                                               
 731          synchronized (sBgLock) {                                                                                  
 732              checkItemInfoLocked(itemId, item, stackTrace);                                                        
 733                                                                                                                    
 734              if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&                                 
 735                      item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                             
 736                  // Item is in a folder, make sure this folder exists                                              
 737                  if (!sBgFolders.containsKey(item.container)) {                                                    
 738                      // An items container is being set to a that of an item which is not in                       
 739                      // the list of Folders.                                                                       
 740                      String msg = "item: " + item + " container being set to: " +                                  
 741                              item.container + ", not in the list of folders";                                      
 742                      Log.e(TAG, msg);                                                                              
 743                  }                                                                                                 
 744              }                                                                                                     
 745                                                                                                                    
 746              // Items are added/removed from the corresponding FolderInfo elsewhere, such                          
 747              // as in Workspace.onDrop. Here, we just add/remove them from the list of items                       
 748              // that are on the desktop, as appropriate                                                            
 749              ItemInfo modelItem = sBgItemsIdMap.get(itemId);                                                       
 750              if (modelItem != null &&                                                                              
 751                      (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||                       
 752                       modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {                      
 753                  switch (modelItem.itemType) {                                                                     
 754                      case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                                        
 755                      case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                           
 756                      case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                             
 757                          if (!sBgWorkspaceItems.contains(modelItem)) {                                             
 758                              sBgWorkspaceItems.add(modelItem);                                                     
 759                          }                                                                                         
 760                          break;                                                                                    
 761                      default:                                                                                      
 762                          break;                                                                                    
 763                  }                                                                                                 
 764              } else {                                                                                              
 765                  sBgWorkspaceItems.remove(modelItem);                                                              
 766              }                                                                                                     
 767          }                                                                                                         
 768      }                                                                                                             
 769                                                                                                                    
 770      public void flushWorkerThread() {                                                                             
 771          mFlushingWorkerThread = true;                                                                             
 772          Runnable waiter = new Runnable() {                                                                        
 773                  public void run() {                                                                               
 774                      synchronized (this) {                                                                         
 775                          notifyAll();                                                                              
 776                          mFlushingWorkerThread = false;                                                            
 777                      }                                                                                             
 778                  }                                                                                                 
 779              };                                                                                                    
 780                                                                                                                    
 781          synchronized(waiter) {                                                                                    
 782              runOnWorkerThread(waiter);                                                                            
 783              if (mLoaderTask != null) {                                                                            
 784                  synchronized(mLoaderTask) {                                                                       
 785                      mLoaderTask.notify();                                                                         
 786                  }                                                                                                 
 787              }                                                                                                     
 788              boolean success = false;                                                                              
 789              while (!success) {                                                                                    
 790                  try {                                                                                             
 791                      waiter.wait();                                                                                
 792                      success = true;                                                                               
 793                  } catch (InterruptedException e) {                                                                
 794                  }                                                                                                 
 795              }                                                                                                     
 796          }                                                                                                         
 797      }                                                                                                             
 798                                                                                                                    
 799      /**                                                                                                           
 800       * Move an item in the DB to a new <container, screen, cellX, cellY>                                          
 801       */                                                                                                           
 802      static void moveItemInDatabase(Context context, final ItemInfo item, final long container,                    
 803              final long screenId, final int cellX, final int cellY) {                                              
 804          item.container = container;                                                                               
 805          item.cellX = cellX;                                                                                       
 806          item.cellY = cellY;                                                                                       
 807                                                                                                                    
 808          // We store hotseat items in canonical form which is this orientation invariant position                  
 809          // in the hotseat                                                                                         
 810          if (context instanceof Launcher && screenId < 0 &&                                                        
 811                  container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                                      
 812              item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);                    
 813          } else {                                                                                                  
 814              item.screenId = screenId;                                                                             
 815          }                                                                                                         
 816                                                                                                                    
 817          final ContentValues values = new ContentValues();                                                         
 818          values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                         
 819          values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                                 
 820          values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                                 
 821          values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                             
 822                                                                                                                    
 823          updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");                                  
 824      }                                                                                                             
 825                                                                                                                    
 826      /**                                                                                                           
 827       * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the                        
 828       * cellX, cellY have already been updated on the ItemInfos.                                                   
 829       */                                                                                                           
 830      static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,                             
 831              final long container, final int screen) {                                                             
 832                                                                                                                    
 833          ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();                                  
 834          int count = items.size();                                                                                 
 835                                                                                                                    
 836          for (int i = 0; i < count; i++) {                                                                         
 837              ItemInfo item = items.get(i);                                                                         
 838              item.container = container;                                                                           
 839                                                                                                                    
 840              // We store hotseat items in canonical form which is this orientation invariant position              
 841              // in the hotseat                                                                                     
 842              if (context instanceof Launcher && screen < 0 &&                                                      
 843                      container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                                  
 844                  item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,                   
 845                          item.cellY);                                                                              
 846              } else {                                                                                              
 847                  item.screenId = screen;                                                                           
 848              }                                                                                                     
 849                                                                                                                    
 850              final ContentValues values = new ContentValues();                                                     
 851              values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                     
 852              values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                             
 853              values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                             
 854              values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                         
 855                                                                                                                    
 856              contentValues.add(values);                                                                            
 857          }                                                                                                         
 858          updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");                         
 859      }                                                                                                             
 860                                                                                                                    
 861      /**                                                                                                           
 862       * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>                 
 863       */                                                                                                           
 864      static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,                  
 865              final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {            
 866          item.container = container;                                                                               
 867          item.cellX = cellX;                                                                                       
 868          item.cellY = cellY;                                                                                       
 869          item.spanX = spanX;                                                                                       
 870          item.spanY = spanY;                                                                                       
 871                                                                                                                    
 872          // We store hotseat items in canonical form which is this orientation invariant position                  
 873          // in the hotseat                                                                                         
 874          if (context instanceof Launcher && screenId < 0 &&                                                        
 875                  container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                                      
 876              item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);                    
 877          } else {                                                                                                  
 878              item.screenId = screenId;                                                                             
 879          }                                                                                                         
 880                                                                                                                    
 881          final ContentValues values = new ContentValues();                                                         
 882          values.put(LauncherSettings.Favorites.CONTAINER, item.container);                                         
 883          values.put(LauncherSettings.Favorites.CELLX, item.cellX);                                                 
 884          values.put(LauncherSettings.Favorites.CELLY, item.cellY);                                                 
 885          values.put(LauncherSettings.Favorites.SPANX, item.spanX);                                                 
 886          values.put(LauncherSettings.Favorites.SPANY, item.spanY);                                                 
 887          values.put(LauncherSettings.Favorites.SCREEN, item.screenId);                                             
 888                                                                                                                    
 889          updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");                                
 890      }                                                                                                             
 891                                                                                                                    
 892      /**                                                                                                           
 893       * Update an item to the database in a specified container.                                                   
 894       */                                                                                                           
 895      static void updateItemInDatabase(Context context, final ItemInfo item) {                                      
 896          final ContentValues values = new ContentValues();                                                         
 897 -        item.onAddToDatabase(values);                                                                             
 898 +        item.onAddToDatabase(context, values);                                                                    
 899          item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                         
 900          updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");                                
 901      }                                                                                                             
 902                                                                                                                    
 903      /**                                                                                                           
 904       * Returns true if the shortcuts already exists in the database.                                              
 905       * we identify a shortcut by its title and intent.                                                            
 906       */                                                                                                           
 907      static boolean shortcutExists(Context context, String title, Intent intent) {                                 
 908          final ContentResolver cr = context.getContentResolver();                                                  
 909 +        final Intent intentWithPkg, intentWithoutPkg;                                                             
 910 +                                                                                                                  
 911 +        if (intent.getComponent() != null) {                                                                      
 912 +            // If component is not null, an intent with null package will produce                                 
 913 +            // the same result and should also be a match.                                                        
 914 +            if (intent.getPackage() != null) {                                                                    
 915 +                intentWithPkg = intent;                                                                           
 916 +                intentWithoutPkg = new Intent(intent).setPackage(null);                                           
 917 +            } else {                                                                                              
 918 +                intentWithPkg = new Intent(intent).setPackage(                                                    
 919 +                        intent.getComponent().getPackageName());                                                  
 920 +                intentWithoutPkg = intent;                                                                        
 921 +            }                                                                                                     
 922 +        } else {                                                                                                  
 923 +            intentWithPkg = intent;                                                                               
 924 +            intentWithoutPkg = intent;                                                                            
 925 +        }                                                                                                         
 926          Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,                                               
 927 -            new String[] { "title", "intent" }, "title=? and intent=?",                                           
 928 -            new String[] { title, intent.toUri(0) }, null);                                                       
 929 +            new String[] { "title", "intent" }, "title=? and (intent=? or intent=?)",                             
 930 +            new String[] { title, intentWithPkg.toUri(0), intentWithoutPkg.toUri(0) }, null);                     
 931          boolean result = false;                                                                                   
 932          try {                                                                                                     
 933              result = c.moveToFirst();                                                                             
 934          } finally {                                                                                               
 935              c.close();                                                                                            
 936          }                                                                                                         
 937          return result;                                                                                            
 938 +    }                                                                                                             
 939 +                                                                                                                  
 940 +    /**                                                                                                           
 941 +     * Returns true if the promise shortcuts with the same package name exists on the workspace.                  
 942 +     */                                                                                                           
 943 +    static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {                         
 944 +        final ComponentName component = intent.getComponent();                                                    
 945 +        if (component == null) {                                                                                  
 946 +            return false;                                                                                         
 947 +        }                                                                                                         
 948 +        return !getItemsByPackageName(component.getPackageName(), user).isEmpty();                                
 949      }                                                                                                             
 950                                                                                                                    
 951      /**                                                                                                           
 952       * Returns an ItemInfo array containing all the items in the LauncherModel.                                   
 953       * The ItemInfo.id is not set through this function.                                                          
 954       */                                                                                                           
 955      static ArrayList<ItemInfo> getItemsInLocalCoordinates(Context context) {                                      
 956          ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                                    
 957          final ContentResolver cr = context.getContentResolver();                                                  
 958          Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, new String[] {                                
 959                  LauncherSettings.Favorites.ITEM_TYPE, LauncherSettings.Favorites.CONTAINER,                       
 960 -                LauncherSettings.Favorites.SCREEN, LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CE🔵
 961 -                LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY }, null, null, null);          
 962 +                LauncherSettings.Favorites.SCREEN,                                                                
 963 +                LauncherSettings.Favorites.CELLX, LauncherSettings.Favorites.CELLY,                               
 964 +                LauncherSettings.Favorites.SPANX, LauncherSettings.Favorites.SPANY,                               
 965 +                LauncherSettings.Favorites.PROFILE_ID }, null, null, null);                                       
 966                                                                                                                    
 967          final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);                  
 968          final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);                 
 969          final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);                       
 970          final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                         
 971          final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                         
 972          final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);                         
 973          final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);                         
 974 -                                                                                                                  
 975 +        final int profileIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.PROFILE_ID);                
 976 +        UserManagerCompat userManager = UserManagerCompat.getInstance(context);                                   
 977          try {                                                                                                     
 978              while (c.moveToNext()) {                                                                              
 979                  ItemInfo item = new ItemInfo();                                                                   
 980                  item.cellX = c.getInt(cellXIndex);                                                                
 981                  item.cellY = c.getInt(cellYIndex);                                                                
 982                  item.spanX = Math.max(1, c.getInt(spanXIndex));                                                   
 983                  item.spanY = Math.max(1, c.getInt(spanYIndex));                                                   
 984                  item.container = c.getInt(containerIndex);                                                        
 985                  item.itemType = c.getInt(itemTypeIndex);                                                          
 986                  item.screenId = c.getInt(screenIndex);                                                            
 987 -                                                                                                                  
 988 -                items.add(item);                                                                                  
 989 +                long serialNumber = c.getInt(profileIdIndex);                                                     
 990 +                item.user = userManager.getUserForSerialNumber(serialNumber);                                     
 991 +                // Skip if user has been deleted.                                                                 
 992 +                if (item.user != null) {                                                                          
 993 +                    items.add(item);                                                                              
 994 +                }                                                                                                 
 995              }                                                                                                     
 996          } catch (Exception e) {                                                                                   
 997              items.clear();                                                                                        
 998          } finally {                                                                                               
 999              c.close();                                                                                            
1000          }                                                                                                         
1001                                                                                                                    
1002          return items;                                                                                             
1003      }                                                                                                             
1004                                                                                                                    
1005      /**                                                                                                           
1006       * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.                
1007       */                                                                                                           
1008      FolderInfo getFolderById(Context context, HashMap<Long,FolderInfo> folderList, long id) {                     
1009          final ContentResolver cr = context.getContentResolver();                                                  
1010          Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,                                         
1011                  "_id=? and (itemType=? or itemType=?)",                                                           
1012                  new String[] { String.valueOf(id),                                                                
1013                          String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);                      
1014                                                                                                                    
1015          try {                                                                                                     
1016              if (c.moveToFirst()) {                                                                                
1017                  final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);          
1018                  final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);                 
1019                  final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);         
1020                  final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);               
1021                  final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);                 
1022                  final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);                 
1023                                                                                                                    
1024                  FolderInfo folderInfo = null;                                                                     
1025                  switch (c.getInt(itemTypeIndex)) {                                                                
1026                      case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                             
1027                          folderInfo = findOrMakeFolder(folderList, id);                                            
1028                          break;                                                                                    
1029                  }                                                                                                 
1030                                                                                                                    
1031                  folderInfo.title = c.getString(titleIndex);                                                       
1032                  folderInfo.id = id;                                                                               
1033                  folderInfo.container = c.getInt(containerIndex);                                                  
1034                  folderInfo.screenId = c.getInt(screenIndex);                                                      
1035                  folderInfo.cellX = c.getInt(cellXIndex);                                                          
1036                  folderInfo.cellY = c.getInt(cellYIndex);                                                          
1037                                                                                                                    
1038                  return folderInfo;                                                                                
1039              }                                                                                                     
1040          } finally {                                                                                               
1041              c.close();                                                                                            
1042          }                                                                                                         
1043                                                                                                                    
1044          return null;                                                                                              
1045      }                                                                                                             
1046                                                                                                                    
1047      /**                                                                                                           
1048       * Add an item to the database in a specified container. Sets the container, screen, cellX and                
1049       * cellY fields of the item. Also assigns an ID to the item.                                                  
1050       */                                                                                                           
1051      static void addItemToDatabase(Context context, final ItemInfo item, final long container,                     
1052              final long screenId, final int cellX, final int cellY, final boolean notify) {                        
1053          item.container = container;                                                                               
1054          item.cellX = cellX;                                                                                       
1055          item.cellY = cellY;                                                                                       
1056          // We store hotseat items in canonical form which is this orientation invariant position                  
1057          // in the hotseat                                                                                         
1058          if (context instanceof Launcher && screenId < 0 &&                                                        
1059                  container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                                      
1060              item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);                    
1061          } else {                                                                                                  
1062              item.screenId = screenId;                                                                             
1063          }                                                                                                         
1064                                                                                                                    
1065          final ContentValues values = new ContentValues();                                                         
1066          final ContentResolver cr = context.getContentResolver();                                                  
1067 -        item.onAddToDatabase(values);                                                                             
1068 +        item.onAddToDatabase(context, values);                                                                    
1069                                                                                                                    
1070          item.id = LauncherAppState.getLauncherProvider().generateNewItemId();                                     
1071          values.put(LauncherSettings.Favorites._ID, item.id);                                                      
1072          item.updateValuesWithCoordinates(values, item.cellX, item.cellY);                                         
1073                                                                                                                    
1074 +        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();                                   
1075          Runnable r = new Runnable() {                                                                             
1076              public void run() {                                                                                   
1077                  cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :                                       
1078                          LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);                          
1079                                                                                                                    
1080                  // Lock on mBgLock *after* the db operation                                                       
1081                  synchronized (sBgLock) {                                                                          
1082 -                    checkItemInfoLocked(item.id, item, null);                                                     
1083 +                    checkItemInfoLocked(item.id, item, stackTrace);                                               
1084                      sBgItemsIdMap.put(item.id, item);                                                             
1085                      switch (item.itemType) {                                                                      
1086                          case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                         
1087                              sBgFolders.put(item.id, (FolderInfo) item);                                           
1088                              // Fall through                                                                       
1089                          case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                                    
1090                          case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                       
1091                              if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||                 
1092                                      item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {             
1093                                  sBgWorkspaceItems.add(item);                                                      
1094                              } else {                                                                              
1095                                  if (!sBgFolders.containsKey(item.container)) {                                    
1096                                      // Adding an item to a folder that doesn't exist.                             
1097                                      String msg = "adding item: " + item + " to a folder that " +                  
1098                                              " doesn't exist";                                                     
1099                                      Log.e(TAG, msg);                                                              
1100                                  }                                                                                 
1101                              }                                                                                     
1102                              break;                                                                                
1103                          case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                                      
1104                              sBgAppWidgets.add((LauncherAppWidgetInfo) item);                                      
1105                              break;                                                                                
1106                      }                                                                                             
1107                  }                                                                                                 
1108              }                                                                                                     
1109          };                                                                                                        
1110          runOnWorkerThread(r);                                                                                     
1111      }                                                                                                             
1112                                                                                                                    
1113      /**                                                                                                           
1114       * Creates a new unique child id, for a given cell span across all layouts.                                   
1115       */                                                                                                           
1116      static int getCellLayoutChildId(                                                                              
1117              long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {                  
1118          return (((int) container & 0xFF) << 24)                                                                   
1119                  | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);                   
1120      }                                                                                                             
1121                                                                                                                    
1122 +    private static ArrayList<ItemInfo> getItemsByPackageName(                                                     
1123 +            final String pn, final UserHandleCompat user) {                                                       
1124 +        ItemInfoFilter filter  = new ItemInfoFilter() {                                                           
1125 +            @Override                                                                                             
1126 +            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                         
1127 +                return cn.getPackageName().equals(pn) && info.user.equals(user);                                  
1128 +            }                                                                                                     
1129 +        };                                                                                                        
1130 +        return filterItemInfos(sBgItemsIdMap.values(), filter);                                                   
1131 +    }                                                                                                             
1132 +                                                                                                                  
1133 +    /**                                                                                                           
1134 +     * Removes all the items from the database corresponding to the specified package.                            
1135 +     */                                                                                                           
1136 +    static void deletePackageFromDatabase(Context context, final String pn,                                       
1137 +            final UserHandleCompat user) {                                                                        
1138 +        deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));                                        
1139 +    }                                                                                                             
1140 +                                                                                                                  
1141      /**                                                                                                           
1142       * Removes the specified item from the database                                                               
1143       * @param context                                                                                             
1144       * @param item                                                                                                
1145       */                                                                                                           
1146      static void deleteItemFromDatabase(Context context, final ItemInfo item) {                                    
1147 +        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();                                                    
1148 +        items.add(item);                                                                                          
1149 +        deleteItemsFromDatabase(context, items);                                                                  
1150 +    }                                                                                                             
1151 +                                                                                                                  
1152 +    /**                                                                                                           
1153 +     * Removes the specified items from the database                                                              
1154 +     * @param context                                                                                             
1155 +     * @param item                                                                                                
1156 +     */                                                                                                           
1157 +    static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {                       
1158          final ContentResolver cr = context.getContentResolver();                                                  
1159 -        final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);                         
1160                                                                                                                    
1161          Runnable r = new Runnable() {                                                                             
1162              public void run() {                                                                                   
1163 -                cr.delete(uriToDelete, null, null);                                                               
1164 -                                                                                                                  
1165 -                // Lock on mBgLock *after* the db operation                                                       
1166 -                synchronized (sBgLock) {                                                                          
1167 -                    switch (item.itemType) {                                                                      
1168 -                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                         
1169 -                            sBgFolders.remove(item.id);                                                           
1170 -                            for (ItemInfo info: sBgItemsIdMap.values()) {                                         
1171 -                                if (info.container == item.id) {                                                  
1172 -                                    // We are deleting a folder which still contains items that                   
1173 -                                    // think they are contained by that folder.                                   
1174 -                                    String msg = "deleting a folder (" + item + ") which still " +                
1175 -                                            "contains items (" + info + ")";                                      
1176 -                                    Log.e(TAG, msg);                                                              
1177 +                for (ItemInfo item : items) {                                                                     
1178 +                    final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);                     
1179 +                    cr.delete(uri, null, null);                                                                   
1180 +                                                                                                                  
1181 +                    // Lock on mBgLock *after* the db operation                                                   
1182 +                    synchronized (sBgLock) {                                                                      
1183 +                        switch (item.itemType) {                                                                  
1184 +                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                     
1185 +                                sBgFolders.remove(item.id);                                                       
1186 +                                for (ItemInfo info: sBgItemsIdMap.values()) {                                     
1187 +                                    if (info.container == item.id) {                                              
1188 +                                        // We are deleting a folder which still contains items that               
1189 +                                        // think they are contained by that folder.                               
1190 +                                        String msg = "deleting a folder (" + item + ") which still " +            
1191 +                                                "contains items (" + info + ")";                                  
1192 +                                        Log.e(TAG, msg);                                                          
1193 +                                    }                                                                             
1194                                  }                                                                                 
1195 -                            }                                                                                     
1196 -                            sBgWorkspaceItems.remove(item);                                                       
1197 -                            break;                                                                                
1198 -                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                                    
1199 -                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                       
1200 -                            sBgWorkspaceItems.remove(item);                                                       
1201 -                            break;                                                                                
1202 -                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                                      
1203 -                            sBgAppWidgets.remove((LauncherAppWidgetInfo) item);                                   
1204 -                            break;                                                                                
1205 -                    }                                                                                             
1206 -                    sBgItemsIdMap.remove(item.id);                                                                
1207 -                    sBgDbIconCache.remove(item);                                                                  
1208 +                                sBgWorkspaceItems.remove(item);                                                   
1209 +                                break;                                                                            
1210 +                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                                
1211 +                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                   
1212 +                                sBgWorkspaceItems.remove(item);                                                   
1213 +                                break;                                                                            
1214 +                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                                  
1215 +                                sBgAppWidgets.remove((LauncherAppWidgetInfo) item);                               
1216 +                                break;                                                                            
1217 +                        }                                                                                         
1218 +                        sBgItemsIdMap.remove(item.id);                                                            
1219 +                        sBgDbIconCache.remove(item);                                                              
1220 +                    }                                                                                             
1221                  }                                                                                                 
1222              }                                                                                                     
1223          };                                                                                                        
1224          runOnWorkerThread(r);                                                                                     
1225      }                                                                                                             
1226                                                                                                                    
1227      /**                                                                                                           
1228       * Update the order of the workspace screens in the database. The array list contains                         
1229       * a list of screen ids in the order that they should appear.                                                 
1230       */                                                                                                           
1231      void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {                             
1232          // Log to disk                                                                                            
1233          Launcher.addDumpLog(TAG, "11683562 - updateWorkspaceScreenOrder()", true);                                
1234          Launcher.addDumpLog(TAG, "11683562 -   screens: " + TextUtils.join(", ", screens), true);                 
1235                                                                                                                    
1236          final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);                                         
1237          final ContentResolver cr = context.getContentResolver();                                                  
1238          final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                                            
1239                                                                                                                    
1240          // Remove any negative screen ids -- these aren't persisted                                               
1241          Iterator<Long> iter = screensCopy.iterator();                                                             
1242          while (iter.hasNext()) {                                                                                  
1243              long id = iter.next();                                                                                
1244              if (id < 0) {                                                                                         
1245                  iter.remove();                                                                                    
1246              }                                                                                                     
1247          }                                                                                                         
1248                                                                                                                    
1249          Runnable r = new Runnable() {                                                                             
1250              @Override                                                                                             
1251              public void run() {                                                                                   
1252 +                ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();              
1253                  // Clear the table                                                                                
1254 -                cr.delete(uri, null, null);                                                                       
1255 +                ops.add(ContentProviderOperation.newDelete(uri).build());                                         
1256                  int count = screensCopy.size();                                                                   
1257 -                ContentValues[] values = new ContentValues[count];                                                
1258                  for (int i = 0; i < count; i++) {                                                                 
1259                      ContentValues v = new ContentValues();                                                        
1260                      long screenId = screensCopy.get(i);                                                           
1261                      v.put(LauncherSettings.WorkspaceScreens._ID, screenId);                                       
1262                      v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);                                      
1263 -                    values[i] = v;                                                                                
1264 -                }                                                                                                 
1265 -                cr.bulkInsert(uri, values);                                                                       
1266 +                    ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());                       
1267 +                }                                                                                                 
1268 +                                                                                                                  
1269 +                try {                                                                                             
1270 +                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);                                               
1271 +                } catch (Exception ex) {                                                                          
1272 +                    throw new RuntimeException(ex);                                                               
1273 +                }                                                                                                 
1274                                                                                                                    
1275                  synchronized (sBgLock) {                                                                          
1276                      sBgWorkspaceScreens.clear();                                                                  
1277                      sBgWorkspaceScreens.addAll(screensCopy);                                                      
1278                  }                                                                                                 
1279              }                                                                                                     
1280          };                                                                                                        
1281          runOnWorkerThread(r);                                                                                     
1282      }                                                                                                             
1283                                                                                                                    
1284      /**                                                                                                           
1285       * Remove the contents of the specified folder from the database                                              
1286       */                                                                                                           
1287      static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {                        
1288          final ContentResolver cr = context.getContentResolver();                                                  
1289                                                                                                                    
1290          Runnable r = new Runnable() {                                                                             
1291              public void run() {                                                                                   
1292                  cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);                  
1293                  // Lock on mBgLock *after* the db operation                                                       
1294                  synchronized (sBgLock) {                                                                          
1295                      sBgItemsIdMap.remove(info.id);                                                                
1296                      sBgFolders.remove(info.id);                                                                   
1297                      sBgDbIconCache.remove(info);                                                                  
1298                      sBgWorkspaceItems.remove(info);                                                               
1299                  }                                                                                                 
1300                                                                                                                    
1301                  cr.delete(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,                                 
1302                          LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);                              
1303                  // Lock on mBgLock *after* the db operation                                                       
1304                  synchronized (sBgLock) {                                                                          
1305                      for (ItemInfo childInfo : info.contents) {                                                    
1306                          sBgItemsIdMap.remove(childInfo.id);                                                       
1307                          sBgDbIconCache.remove(childInfo);                                                         
1308                      }                                                                                             
1309                  }                                                                                                 
1310              }                                                                                                     
1311          };                                                                                                        
1312          runOnWorkerThread(r);                                                                                     
1313      }                                                                                                             
1314                                                                                                                    
1315      /**                                                                                                           
1316       * Set this as the current Launcher activity object for the loader.                                           
1317       */                                                                                                           
1318      public void initialize(Callbacks callbacks) {                                                                 
1319          synchronized (mLock) {                                                                                    
1320              mCallbacks = new WeakReference<Callbacks>(callbacks);                                                 
1321          }                                                                                                         
1322      }                                                                                                             
1323                                                                                                                    
1324 +    @Override                                                                                                     
1325 +    public void onPackageChanged(String packageName, UserHandleCompat user) {                                     
1326 +        int op = PackageUpdatedTask.OP_UPDATE;                                                                    
1327 +        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                            
1328 +                user));                                                                                           
1329 +    }                                                                                                             
1330 +                                                                                                                  
1331 +    @Override                                                                                                     
1332 +    public void onPackageRemoved(String packageName, UserHandleCompat user) {                                     
1333 +        int op = PackageUpdatedTask.OP_REMOVE;                                                                    
1334 +        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                            
1335 +                user));                                                                                           
1336 +    }                                                                                                             
1337 +                                                                                                                  
1338 +    @Override                                                                                                     
1339 +    public void onPackageAdded(String packageName, UserHandleCompat user) {                                       
1340 +        int op = PackageUpdatedTask.OP_ADD;                                                                       
1341 +        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },                            
1342 +                user));                                                                                           
1343 +    }                                                                                                             
1344 +                                                                                                                  
1345 +    @Override                                                                                                     
1346 +    public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,                                 
1347 +            boolean replacing) {                                                                                  
1348 +        if (!replacing) {                                                                                         
1349 +            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames,                 
1350 +                    user));                                                                                       
1351 +            if (mAppsCanBeOnRemoveableStorage) {                                                                  
1352 +                // Only rebind if we support removable storage. It catches the                                    
1353 +                // case where                                                                                     
1354 +                // apps on the external sd card need to be reloaded                                               
1355 +                startLoaderFromBackground();                                                                      
1356 +            }                                                                                                     
1357 +        } else {                                                                                                  
1358 +            // If we are replacing then just update the packages in the list                                      
1359 +            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,                            
1360 +                    packageNames, user));                                                                         
1361 +        }                                                                                                         
1362 +    }                                                                                                             
1363 +                                                                                                                  
1364 +    @Override                                                                                                     
1365 +    public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,                               
1366 +            boolean replacing) {                                                                                  
1367 +        if (!replacing) {                                                                                         
1368 +            enqueuePackageUpdated(new PackageUpdatedTask(                                                         
1369 +                    PackageUpdatedTask.OP_UNAVAILABLE, packageNames,                                              
1370 +                    user));                                                                                       
1371 +        }                                                                                                         
1372 +                                                                                                                  
1373 +    }                                                                                                             
1374 +                                                                                                                  
1375      /**                                                                                                           
1376       * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and                                 
1377       * ACTION_PACKAGE_CHANGED.                                                                                    
1378       */                                                                                                           
1379      @Override                                                                                                     
1380      public void onReceive(Context context, Intent intent) {                                                       
1381 -        if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);                                              
1382 +        if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);                                             
1383                                                                                                                    
1384          final String action = intent.getAction();                                                                 
1385 -                                                                                                                  
1386 -        if (Intent.ACTION_PACKAGE_CHANGED.equals(action)                                                          
1387 -                || Intent.ACTION_PACKAGE_REMOVED.equals(action)                                                   
1388 -                || Intent.ACTION_PACKAGE_ADDED.equals(action)) {                                                  
1389 -            final String packageName = intent.getData().getSchemeSpecificPart();                                  
1390 -            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);                      
1391 -                                                                                                                  
1392 -            int op = PackageUpdatedTask.OP_NONE;                                                                  
1393 -                                                                                                                  
1394 -            if (packageName == null || packageName.length() == 0) {                                               
1395 -                // they sent us a bad intent                                                                      
1396 -                return;                                                                                           
1397 -            }                                                                                                     
1398 -                                                                                                                  
1399 -            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {                                                   
1400 -                op = PackageUpdatedTask.OP_UPDATE;                                                                
1401 -            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {                                            
1402 -                if (!replacing) {                                                                                 
1403 -                    op = PackageUpdatedTask.OP_REMOVE;                                                            
1404 -                }                                                                                                 
1405 -                // else, we are replacing the package, so a PACKAGE_ADDED will be sent                            
1406 -                // later, we will update the package at this time                                                 
1407 -            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {                                              
1408 -                if (!replacing) {                                                                                 
1409 -                    op = PackageUpdatedTask.OP_ADD;                                                               
1410 -                } else {                                                                                          
1411 -                    op = PackageUpdatedTask.OP_UPDATE;                                                            
1412 -                }                                                                                                 
1413 -            }                                                                                                     
1414 -                                                                                                                  
1415 -            if (op != PackageUpdatedTask.OP_NONE) {                                                               
1416 -                enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName }));                  
1417 -            }                                                                                                     
1418 -                                                                                                                  
1419 -        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {                                
1420 -            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);                      
1421 -            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);                    
1422 -            if (!replacing) {                                                                                     
1423 -                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));               
1424 -                if (mAppsCanBeOnRemoveableStorage) {                                                              
1425 -                    // Only rebind if we support removable storage.  It catches the case where                    
1426 -                    // apps on the external sd card need to be reloaded                                           
1427 -                    startLoaderFromBackground();                                                                  
1428 -                }                                                                                                 
1429 -            } else {                                                                                              
1430 -                // If we are replacing then just update the packages in the list                                  
1431 -                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,                        
1432 -                        packages));                                                                               
1433 -            }                                                                                                     
1434 -        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {                              
1435 -            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);                      
1436 -            if (!replacing) {                                                                                     
1437 -                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);                
1438 -                enqueuePackageUpdated(new PackageUpdatedTask(                                                     
1439 -                            PackageUpdatedTask.OP_UNAVAILABLE, packages));                                        
1440 -            }                                                                                                     
1441 -            // else, we are replacing the packages, so ignore this event and wait for                             
1442 -            // EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time                                
1443 -        } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {                                                 
1444 +        if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {                                                        
1445              // If we have changed locale we need to clear out the labels in all apps/workspace.                   
1446              forceReload();                                                                                        
1447          } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {                                          
1448               // Check if configuration change was an mcc/mnc change which would affect app resources              
1449               // and we would need to clear out the labels in all apps/workspace. Same handling as                 
1450               // above for ACTION_LOCALE_CHANGED                                                                   
1451               Configuration currentConfig = context.getResources().getConfiguration();                             
1452               if (mPreviousConfigMcc != currentConfig.mcc) {                                                       
1453                     Log.d(TAG, "Reload apps on config change. curr_mcc:"                                           
1454                         + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);                                   
1455                     forceReload();                                                                                 
1456               }                                                                                                    
1457               // Update previousConfig                                                                             
1458               mPreviousConfigMcc = currentConfig.mcc;                                                              
1459          } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action) ||                          
1460                     SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED.equals(action)) {                              
1461              if (mCallbacks != null) {                                                                             
1462                  Callbacks callbacks = mCallbacks.get();                                                           
1463                  if (callbacks != null) {                                                                          
1464                      callbacks.bindSearchablesChanged();                                                           
1465                  }                                                                                                 
1466              }                                                                                                     
1467          }                                                                                                         
1468      }                                                                                                             
1469                                                                                                                    
1470 -    private void forceReload() {                                                                                  
1471 +    void forceReload() {                                                                                          
1472          resetLoadedState(true, true);                                                                             
1473                                                                                                                    
1474          // Do this here because if the launcher activity is running it will be restarted.                         
1475          // If it's not running startLoaderFromBackground will merely tell it that it needs                        
1476          // to reload.                                                                                             
1477          startLoaderFromBackground();                                                                              
1478      }                                                                                                             
1479                                                                                                                    
1480      public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {                      
1481          synchronized (mLock) {                                                                                    
1482              // Stop any existing loaders first, so they don't set mAllAppsLoaded or                               
1483              // mWorkspaceLoaded to true later                                                                     
1484              stopLoaderLocked();                                                                                   
1485              if (resetAllAppsLoaded) mAllAppsLoaded = false;                                                       
1486              if (resetWorkspaceLoaded) mWorkspaceLoaded = false;                                                   
1487          }                                                                                                         
1488      }                                                                                                             
1489                                                                                                                    
1490      /**                                                                                                           
1491       * When the launcher is in the background, it's possible for it to miss paired                                
1492       * configuration changes.  So whenever we trigger the loader from the background                              
1493       * tell the launcher that it needs to re-run the loader when it comes back instead                            
1494       * of doing it now.                                                                                           
1495       */                                                                                                           
1496      public void startLoaderFromBackground() {                                                                     
1497          boolean runLoader = false;                                                                                
1498          if (mCallbacks != null) {                                                                                 
1499              Callbacks callbacks = mCallbacks.get();                                                               
1500              if (callbacks != null) {                                                                              
1501                  // Only actually run the loader if they're not paused.                                            
1502                  if (!callbacks.setLoadOnResume()) {                                                               
1503                      runLoader = true;                                                                             
1504                  }                                                                                                 
1505              }                                                                                                     
1506          }                                                                                                         
1507          if (runLoader) {                                                                                          
1508              startLoader(false, PagedView.INVALID_RESTORE_PAGE);                                                   
1509          }                                                                                                         
1510      }                                                                                                             
1511                                                                                                                    
1512      // If there is already a loader task running, tell it to stop.                                                
1513      // returns true if isLaunching() was true on the old task                                                     
1514      private boolean stopLoaderLocked() {                                                                          
1515          boolean isLaunching = false;                                                                              
1516          LoaderTask oldTask = mLoaderTask;                                                                         
1517          if (oldTask != null) {                                                                                    
1518              if (oldTask.isLaunching()) {                                                                          
1519                  isLaunching = true;                                                                               
1520              }                                                                                                     
1521              oldTask.stopLocked();                                                                                 
1522          }                                                                                                         
1523          return isLaunching;                                                                                       
1524      }                                                                                                             
1525                                                                                                                    
1526 +    public boolean isCurrentCallbacks(Callbacks callbacks) {                                                      
1527 +        return (mCallbacks != null && mCallbacks.get() == callbacks);                                             
1528 +    }                                                                                                             
1529 +                                                                                                                  
1530      public void startLoader(boolean isLaunching, int synchronousBindPage) {                                       
1531          startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);                                          
1532      }                                                                                                             
1533                                                                                                                    
1534      public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {                        
1535          synchronized (mLock) {                                                                                    
1536              if (DEBUG_LOADERS) {                                                                                  
1537                  Log.d(TAG, "startLoader isLaunching=" + isLaunching);                                             
1538              }                                                                                                     
1539                                                                                                                    
1540              // Clear any deferred bind-runnables from the synchronized load process                               
1541              // We must do this before any loading/binding is scheduled below.                                     
1542 -            mDeferredBindRunnables.clear();                                                                       
1543 +            synchronized (mDeferredBindRunnables) {                                                               
1544 +                mDeferredBindRunnables.clear();                                                                   
1545 +            }                                                                                                     
1546                                                                                                                    
1547              // Don't bother to start the thread if we know it's not going to do anything                          
1548              if (mCallbacks != null && mCallbacks.get() != null) {                                                 
1549                  // If there is already one running, tell it to stop.                                              
1550                  // also, don't downgrade isLaunching if we're already running                                     
1551                  isLaunching = isLaunching || stopLoaderLocked();                                                  
1552                  mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);                          
1553                  if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE                                         
1554                          && mAllAppsLoaded && mWorkspaceLoaded) {                                                  
1555                      mLoaderTask.runBindSynchronousPage(synchronousBindPage);                                      
1556                  } else {                                                                                          
1557                      sWorkerThread.setPriority(Thread.NORM_PRIORITY);                                              
1558                      sWorker.post(mLoaderTask);                                                                    
1559                  }                                                                                                 
1560              }                                                                                                     
1561          }                                                                                                         
1562      }                                                                                                             
1563                                                                                                                    
1564      void bindRemainingSynchronousPages() {                                                                        
1565          // Post the remaining side pages to be loaded                                                             
1566          if (!mDeferredBindRunnables.isEmpty()) {                                                                  
1567 -            for (final Runnable r : mDeferredBindRunnables) {                                                     
1568 +            Runnable[] deferredBindRunnables = null;                                                              
1569 +            synchronized (mDeferredBindRunnables) {                                                               
1570 +                deferredBindRunnables = mDeferredBindRunnables.toArray(                                           
1571 +                        new Runnable[mDeferredBindRunnables.size()]);                                             
1572 +                mDeferredBindRunnables.clear();                                                                   
1573 +            }                                                                                                     
1574 +            for (final Runnable r : deferredBindRunnables) {                                                      
1575                  mHandler.post(r, MAIN_THREAD_BINDING_RUNNABLE);                                                   
1576              }                                                                                                     
1577 -            mDeferredBindRunnables.clear();                                                                       
1578          }                                                                                                         
1579      }                                                                                                             
1580                                                                                                                    
1581      public void stopLoader() {                                                                                    
1582          synchronized (mLock) {                                                                                    
1583              if (mLoaderTask != null) {                                                                            
1584                  mLoaderTask.stopLocked();                                                                         
1585              }                                                                                                     
1586          }                                                                                                         
1587      }                                                                                                             
1588                                                                                                                    
1589      /** Loads the workspace screens db into a map of Rank -> ScreenId */                                          
1590      private static TreeMap<Integer, Long> loadWorkspaceScreensDb(Context context) {                               
1591          final ContentResolver contentResolver = context.getContentResolver();                                     
1592          final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;                                     
1593          final Cursor sc = contentResolver.query(screensUri, null, null, null, null);                              
1594          TreeMap<Integer, Long> orderedScreens = new TreeMap<Integer, Long>();                                     
1595                                                                                                                    
1596          try {                                                                                                     
1597              final int idIndex = sc.getColumnIndexOrThrow(                                                         
1598                      LauncherSettings.WorkspaceScreens._ID);                                                       
1599              final int rankIndex = sc.getColumnIndexOrThrow(                                                       
1600                      LauncherSettings.WorkspaceScreens.SCREEN_RANK);                                               
1601              while (sc.moveToNext()) {                                                                             
1602                  try {                                                                                             
1603                      long screenId = sc.getLong(idIndex);                                                          
1604                      int rank = sc.getInt(rankIndex);                                                              
1605                      orderedScreens.put(rank, screenId);                                                           
1606                  } catch (Exception e) {                                                                           
1607                      Launcher.addDumpLog(TAG, "Desktop items loading interrupted - invalid screens: " + e, true);  
1608                  }                                                                                                 
1609              }                                                                                                     
1610          } finally {                                                                                               
1611              sc.close();                                                                                           
1612          }                                                                                                         
1613                                                                                                                    
1614          // Log to disk                                                                                            
1615          Launcher.addDumpLog(TAG, "11683562 - loadWorkspaceScreensDb()", true);                                    
1616          ArrayList<String> orderedScreensPairs= new ArrayList<String>();                                           
1617          for (Integer i : orderedScreens.keySet()) {                                                               
1618              orderedScreensPairs.add("{ " + i + ": " + orderedScreens.get(i) + " }");                              
1619          }                                                                                                         
1620          Launcher.addDumpLog(TAG, "11683562 -   screens: " +                                                       
1621                  TextUtils.join(", ", orderedScreensPairs), true);                                                 
1622          return orderedScreens;                                                                                    
1623      }                                                                                                             
1624                                                                                                                    
1625      public boolean isAllAppsLoaded() {                                                                            
1626          return mAllAppsLoaded;                                                                                    
1627      }                                                                                                             
1628                                                                                                                    
1629      boolean isLoadingWorkspace() {                                                                                
1630          synchronized (mLock) {                                                                                    
1631              if (mLoaderTask != null) {                                                                            
1632                  return mLoaderTask.isLoadingWorkspace();                                                          
1633              }                                                                                                     
1634          }                                                                                                         
1635          return false;                                                                                             
1636      }                                                                                                             
1637                                                                                                                    
1638      /**                                                                                                           
1639       * Runnable for the thread that loads the contents of the launcher:                                           
1640       *   - workspace icons                                                                                        
1641       *   - widgets                                                                                                
1642       *   - all apps icons                                                                                         
1643       */                                                                                                           
1644      private class LoaderTask implements Runnable {                                                                
1645          private Context mContext;                                                                                 
1646          private boolean mIsLaunching;                                                                             
1647          private boolean mIsLoadingAndBindingWorkspace;                                                            
1648          private boolean mStopped;                                                                                 
1649          private boolean mLoadAndBindStepFinished;                                                                 
1650          private int mFlags;                                                                                       
1651                                                                                                                    
1652          private HashMap<Object, CharSequence> mLabelCache;                                                        
1653                                                                                                                    
1654          LoaderTask(Context context, boolean isLaunching, int flags) {                                             
1655              mContext = context;                                                                                   
1656              mIsLaunching = isLaunching;                                                                           
1657              mLabelCache = new HashMap<Object, CharSequence>();                                                    
1658              mFlags = flags;                                                                                       
1659          }                                                                                                         
1660                                                                                                                    
1661          boolean isLaunching() {                                                                                   
1662              return mIsLaunching;                                                                                  
1663          }                                                                                                         
1664                                                                                                                    
1665          boolean isLoadingWorkspace() {                                                                            
1666              return mIsLoadingAndBindingWorkspace;                                                                 
1667          }                                                                                                         
1668                                                                                                                    
1669          /** Returns whether this is an upgrade path */                                                            
1670          private boolean loadAndBindWorkspace() {                                                                  
1671              mIsLoadingAndBindingWorkspace = true;                                                                 
1672                                                                                                                    
1673              // Load the workspace                                                                                 
1674              if (DEBUG_LOADERS) {                                                                                  
1675                  Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);                          
1676              }                                                                                                     
1677                                                                                                                    
1678              boolean isUpgradePath = false;                                                                        
1679              if (!mWorkspaceLoaded) {                                                                              
1680                  isUpgradePath = loadWorkspace();                                                                  
1681                  synchronized (LoaderTask.this) {                                                                  
1682                      if (mStopped) {                                                                               
1683                          return isUpgradePath;                                                                     
1684                      }                                                                                             
1685                      mWorkspaceLoaded = true;                                                                      
1686                  }                                                                                                 
1687              }                                                                                                     
1688                                                                                                                    
1689              // Bind the workspace                                                                                 
1690              bindWorkspace(-1, isUpgradePath);                                                                     
1691              return isUpgradePath;                                                                                 
1692          }                                                                                                         
1693                                                                                                                    
1694          private void waitForIdle() {                                                                              
1695              // Wait until the either we're stopped or the other threads are done.                                 
1696              // This way we don't start loading all apps until the workspace has settled                           
1697              // down.                                                                                              
1698              synchronized (LoaderTask.this) {                                                                      
1699                  final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                    
1700                                                                                                                    
1701                  mHandler.postIdle(new Runnable() {                                                                
1702                          public void run() {                                                                       
1703                              synchronized (LoaderTask.this) {                                                      
1704                                  mLoadAndBindStepFinished = true;                                                  
1705                                  if (DEBUG_LOADERS) {                                                              
1706                                      Log.d(TAG, "done with previous binding step");                                
1707                                  }                                                                                 
1708                                  LoaderTask.this.notify();                                                         
1709                              }                                                                                     
1710                          }                                                                                         
1711                      });                                                                                           
1712                                                                                                                    
1713                  while (!mStopped && !mLoadAndBindStepFinished && !mFlushingWorkerThread) {                        
1714                      try {                                                                                         
1715                          // Just in case mFlushingWorkerThread changes but we aren't woken up,                     
1716                          // wait no longer than 1sec at a time                                                     
1717                          this.wait(1000);                                                                          
1718                      } catch (InterruptedException ex) {                                                           
1719                          // Ignore                                                                                 
1720                      }                                                                                             
1721                  }                                                                                                 
1722                  if (DEBUG_LOADERS) {                                                                              
1723                      Log.d(TAG, "waited "                                                                          
1724                              + (SystemClock.uptimeMillis()-workspaceWaitTime)                                      
1725                              + "ms for previous step to finish binding");                                          
1726                  }                                                                                                 
1727              }                                                                                                     
1728          }                                                                                                         
1729                                                                                                                    
1730          void runBindSynchronousPage(int synchronousBindPage) {                                                    
1731              if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {                                          
1732                  // Ensure that we have a valid page index to load synchronously                                   
1733                  throw new RuntimeException("Should not call runBindSynchronousPage() without " +                  
1734                          "valid page index");                                                                      
1735              }                                                                                                     
1736              if (!mAllAppsLoaded || !mWorkspaceLoaded) {                                                           
1737                  // Ensure that we don't try and bind a specified page when the pages have not been                
1738                  // loaded already (we should load everything asynchronously in that case)                         
1739                  throw new RuntimeException("Expecting AllApps and Workspace to be loaded");                       
1740              }                                                                                                     
1741              synchronized (mLock) {                                                                                
1742                  if (mIsLoaderTaskRunning) {                                                                       
1743                      // Ensure that we are never running the background loading at this point since                
1744                      // we also touch the background collections                                                   
1745                      throw new RuntimeException("Error! Background loading is already running");                   
1746                  }                                                                                                 
1747              }                                                                                                     
1748                                                                                                                    
1749              // XXX: Throw an exception if we are already loading (since we touch the worker thread                
1750              //      data structures, we can't allow any other thread to touch that data, but because              
1751              //      this call is synchronous, we can get away with not locking).                                  
1752                                                                                                                    
1753              // The LauncherModel is static in the LauncherAppState and mHandler may have queued                   
1754              // operations from the previous activity.  We need to ensure that all queued operations               
1755              // are executed before any synchronous binding work is done.                                          
1756              mHandler.flush();                                                                                     
1757                                                                                                                    
1758              // Divide the set of loaded items into those that we are binding synchronously, and                   
1759              // everything else that is to be bound normally (asynchronously).                                     
1760              bindWorkspace(synchronousBindPage, false);                                                            
1761              // XXX: For now, continue posting the binding of AllApps as there are other issues that               
1762              //      arise from that.                                                                              
1763              onlyBindAllApps();                                                                                    
1764          }                                                                                                         
1765                                                                                                                    
1766          public void run() {                                                                                       
1767              boolean isUpgrade = false;                                                                            
1768                                                                                                                    
1769              synchronized (mLock) {                                                                                
1770                  mIsLoaderTaskRunning = true;                                                                      
1771              }                                                                                                     
1772              // Optimize for end-user experience: if the Launcher is up and // running with the                    
1773              // All Apps interface in the foreground, load All Apps first. Otherwise, load the                     
1774              // workspace first (default).                                                                         
1775              keep_running: {                                                                                       
1776                  // Elevate priority when Home launches for the first time to avoid                                
1777                  // starving at boot time. Staring at a blank home is not cool.                                    
1778                  synchronized (mLock) {                                                                            
1779                      if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to " +                                 
1780                              (mIsLaunching ? "DEFAULT" : "BACKGROUND"));                                           
1781                      android.os.Process.setThreadPriority(mIsLaunching                                             
1782                              ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);              
1783                  }                                                                                                 
1784                  if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");                                       
1785                  isUpgrade = loadAndBindWorkspace();                                                               
1786                                                                                                                    
1787                  if (mStopped) {                                                                                   
1788                      break keep_running;                                                                           
1789                  }                                                                                                 
1790                                                                                                                    
1791                  // Whew! Hard work done.  Slow us down, and wait until the UI thread has                          
1792                  // settled down.                                                                                  
1793                  synchronized (mLock) {                                                                            
1794                      if (mIsLaunching) {                                                                           
1795                          if (DEBUG_LOADERS) Log.d(TAG, "Setting thread priority to BACKGROUND");                   
1796                          android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                 
1797                      }                                                                                             
1798                  }                                                                                                 
1799                  waitForIdle();                                                                                    
1800                                                                                                                    
1801                  // second step                                                                                    
1802                  if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");                                        
1803                  loadAndBindAllApps();                                                                             
1804                                                                                                                    
1805                  // Restore the default thread priority after we are done loading items                            
1806                  synchronized (mLock) {                                                                            
1807                      android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);                        
1808                  }                                                                                                 
1809              }                                                                                                     
1810                                                                                                                    
1811              // Update the saved icons if necessary                                                                
1812              if (DEBUG_LOADERS) Log.d(TAG, "Comparing loaded icons to database icons");                            
1813              synchronized (sBgLock) {                                                                              
1814                  for (Object key : sBgDbIconCache.keySet()) {                                                      
1815                      updateSavedIcon(mContext, (ShortcutInfo) key, sBgDbIconCache.get(key));                       
1816                  }                                                                                                 
1817                  sBgDbIconCache.clear();                                                                           
1818              }                                                                                                     
1819                                                                                                                    
1820              if (LauncherAppState.isDisableAllApps()) {                                                            
1821                  // Ensure that all the applications that are in the system are                                    
1822                  // represented on the home screen.                                                                
1823                  if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {                                                
1824                      verifyApplications();                                                                         
1825                  }                                                                                                 
1826              }                                                                                                     
1827                                                                                                                    
1828              // Clear out this reference, otherwise we end up holding it until all of the                          
1829              // callback runnables are done.                                                                       
1830              mContext = null;                                                                                      
1831                                                                                                                    
1832              synchronized (mLock) {                                                                                
1833                  // If we are still the last one to be scheduled, remove ourselves.                                
1834                  if (mLoaderTask == this) {                                                                        
1835                      mLoaderTask = null;                                                                           
1836                  }                                                                                                 
1837                  mIsLoaderTaskRunning = false;                                                                     
1838              }                                                                                                     
1839          }                                                                                                         
1840                                                                                                                    
1841          public void stopLocked() {                                                                                
1842              synchronized (LoaderTask.this) {                                                                      
1843                  mStopped = true;                                                                                  
1844                  this.notify();                                                                                    
1845              }                                                                                                     
1846          }                                                                                                         
1847                                                                                                                    
1848          /**                                                                                                       
1849           * Gets the callbacks object.  If we've been stopped, or if the launcher object                           
1850           * has somehow been garbage collected, return null instead.  Pass in the Callbacks                        
1851           * object that was around when the deferred message was scheduled, and if there's                         
1852           * a new Callbacks object around then also return null.  This will save us from                           
1853           * calling onto it with data that will be ignored.                                                        
1854           */                                                                                                       
1855          Callbacks tryGetCallbacks(Callbacks oldCallbacks) {                                                       
1856              synchronized (mLock) {                                                                                
1857                  if (mStopped) {                                                                                   
1858                      return null;                                                                                  
1859                  }                                                                                                 
1860                                                                                                                    
1861                  if (mCallbacks == null) {                                                                         
1862                      return null;                                                                                  
1863                  }                                                                                                 
1864                                                                                                                    
1865                  final Callbacks callbacks = mCallbacks.get();                                                     
1866                  if (callbacks != oldCallbacks) {                                                                  
1867                      return null;                                                                                  
1868                  }                                                                                                 
1869                  if (callbacks == null) {                                                                          
1870                      Log.w(TAG, "no mCallbacks");                                                                  
1871                      return null;                                                                                  
1872                  }                                                                                                 
1873                                                                                                                    
1874                  return callbacks;                                                                                 
1875              }                                                                                                     
1876          }                                                                                                         
1877                                                                                                                    
1878          private void verifyApplications() {                                                                       
1879              final Context context = mApp.getContext();                                                            
1880                                                                                                                    
1881              // Cross reference all the applications in our apps list with items in the workspace                  
1882              ArrayList<ItemInfo> tmpInfos;                                                                         
1883              ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();                                                
1884              synchronized (sBgLock) {                                                                              
1885                  for (AppInfo app : mBgAllAppsList.data) {                                                         
1886 -                    tmpInfos = getItemInfoForComponentName(app.componentName);                                    
1887 +                    tmpInfos = getItemInfoForComponentName(app.componentName, app.user);                          
1888                      if (tmpInfos.isEmpty()) {                                                                     
1889                          // We are missing an application icon, so add this to the workspace                       
1890                          added.add(app);                                                                           
1891                          // This is a rare event, so lets log it                                                   
1892                          Log.e(TAG, "Missing Application on load: " + app);                                        
1893                      }                                                                                             
1894                  }                                                                                                 
1895              }                                                                                                     
1896              if (!added.isEmpty()) {                                                                               
1897 -                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                      
1898 -                addAndBindAddedApps(context, added, cb, new ArrayList<AppInfo>());                                
1899 +                addAndBindAddedWorkspaceApps(context, added);                                                     
1900              }                                                                                                     
1901          }                                                                                                         
1902                                                                                                                    
1903          // check & update map of what's occupied; used to discard overlapping/invalid items                       
1904          private boolean checkItemPlacement(HashMap<Long, ItemInfo[][]> occupied, ItemInfo item,                   
1905                                             AtomicBoolean deleteOnInvalidPlacement) {                              
1906              LauncherAppState app = LauncherAppState.getInstance();                                                
1907              DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                         
1908              final int countX = (int) grid.numColumns;                                                             
1909              final int countY = (int) grid.numRows;                                                                
1910                                                                                                                    
1911              long containerIndex = item.screenId;                                                                  
1912              if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                                 
1913                  // Return early if we detect that an item is under the hotseat button                             
1914                  if (mCallbacks == null ||                                                                         
1915                          mCallbacks.get().isAllAppsButtonRank((int) item.screenId)) {                              
1916                      deleteOnInvalidPlacement.set(true);                                                           
1917                      Log.e(TAG, "Error loading shortcut into hotseat " + item                                      
1918                              + " into position (" + item.screenId + ":" + item.cellX + ","                         
1919                              + item.cellY + ") occupied by all apps");                                             
1920                      return false;                                                                                 
1921                  }                                                                                                 
1922                                                                                                                    
1923                  final ItemInfo[][] hotseatItems =                                                                 
1924                          occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);                        
1925                                                                                                                    
1926                  if (item.screenId >= grid.numHotseatIcons) {                                                      
1927                      Log.e(TAG, "Error loading shortcut " + item                                                   
1928                              + " into hotseat position " + item.screenId                                           
1929                              + ", position out of bounds: (0 to " + (grid.numHotseatIcons - 1)                     
1930                              + ")");                                                                               
1931                      return false;                                                                                 
1932                  }                                                                                                 
1933                                                                                                                    
1934                  if (hotseatItems != null) {                                                                       
1935                      if (hotseatItems[(int) item.screenId][0] != null) {                                           
1936                          Log.e(TAG, "Error loading shortcut into hotseat " + item                                  
1937                                  + " into position (" + item.screenId + ":" + item.cellX + ","                     
1938                                  + item.cellY + ") occupied by "                                                   
1939                                  + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)                      
1940                                  [(int) item.screenId][0]);                                                        
1941                              return false;                                                                         
1942                      } else {                                                                                      
1943                          hotseatItems[(int) item.screenId][0] = item;                                              
1944                          return true;                                                                              
1945                      }                                                                                             
1946                  } else {                                                                                          
1947                      final ItemInfo[][] items = new ItemInfo[(int) grid.numHotseatIcons][1];                       
1948                      items[(int) item.screenId][0] = item;                                                         
1949                      occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);                     
1950                      return true;                                                                                  
1951                  }                                                                                                 
1952              } else if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {                          
1953                  // Skip further checking if it is not the hotseat or workspace container                          
1954                  return true;                                                                                      
1955              }                                                                                                     
1956                                                                                                                    
1957              if (!occupied.containsKey(item.screenId)) {                                                           
1958                  ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];                                        
1959                  occupied.put(item.screenId, items);                                                               
1960              }                                                                                                     
1961                                                                                                                    
1962              final ItemInfo[][] screens = occupied.get(item.screenId);                                             
1963              if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                                 
1964                      item.cellX < 0 || item.cellY < 0 ||                                                           
1965                      item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {                       
1966                  Log.e(TAG, "Error loading shortcut " + item                                                       
1967                          + " into cell (" + containerIndex + "-" + item.screenId + ":"                             
1968                          + item.cellX + "," + item.cellY                                                           
1969                          + ") out of screen bounds ( " + countX + "x" + countY + ")");                             
1970                  return false;                                                                                     
1971              }                                                                                                     
1972                                                                                                                    
1973              // Check if any workspace icons overlap with each other                                               
1974              for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                          
1975                  for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                                      
1976                      if (screens[x][y] != null) {                                                                  
1977                          Log.e(TAG, "Error loading shortcut " + item                                               
1978                              + " into cell (" + containerIndex + "-" + item.screenId + ":"                         
1979                              + x + "," + y                                                                         
1980                              + ") occupied by "                                                                    
1981                              + screens[x][y]);                                                                     
1982                          return false;                                                                             
1983                      }                                                                                             
1984                  }                                                                                                 
1985              }                                                                                                     
1986              for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {                                          
1987                  for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {                                      
1988                      screens[x][y] = item;                                                                         
1989                  }                                                                                                 
1990              }                                                                                                     
1991                                                                                                                    
1992              return true;                                                                                          
1993          }                                                                                                         
1994                                                                                                                    
1995          /** Clears all the sBg data structures */                                                                 
1996          private void clearSBgDataStructures() {                                                                   
1997              synchronized (sBgLock) {                                                                              
1998                  sBgWorkspaceItems.clear();                                                                        
1999                  sBgAppWidgets.clear();                                                                            
2000                  sBgFolders.clear();                                                                               
2001                  sBgItemsIdMap.clear();                                                                            
2002                  sBgDbIconCache.clear();                                                                           
2003                  sBgWorkspaceScreens.clear();                                                                      
2004              }                                                                                                     
2005          }                                                                                                         
2006                                                                                                                    
2007          /** Returns whether this is an upgrade path */                                                            
2008          private boolean loadWorkspace() {                                                                         
2009              // Log to disk                                                                                        
2010              Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);                                         
2011                                                                                                                    
2012              final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                                        
2013                                                                                                                    
2014              final Context context = mContext;                                                                     
2015              final ContentResolver contentResolver = context.getContentResolver();                                 
2016              final PackageManager manager = context.getPackageManager();                                           
2017              final AppWidgetManager widgets = AppWidgetManager.getInstance(context);                               
2018              final boolean isSafeMode = manager.isSafeMode();                                                      
2019 +            final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                      
2020 +            final boolean isSdCardReady = context.registerReceiver(null,                                          
2021 +                    new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;                                      
2022                                                                                                                    
2023              LauncherAppState app = LauncherAppState.getInstance();                                                
2024              DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                         
2025              int countX = (int) grid.numColumns;                                                                   
2026              int countY = (int) grid.numRows;                                                                      
2027                                                                                                                    
2028              if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {                                                    
2029                  Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);                     
2030                  LauncherAppState.getLauncherProvider().deleteDatabase();                                          
2031              }                                                                                                     
2032                                                                                                                    
2033              if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {                                                  
2034                  // append the user's Launcher2 shortcuts                                                          
2035                  Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);                        
2036                  LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();                               
2037              } else {                                                                                              
2038                  // Make sure the default workspace is loaded                                                      
2039                  Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);                      
2040 -                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);                        
2041 -            }                                                                                                     
2042 -                                                                                                                  
2043 -            // Check if we need to do any upgrade-path logic                                                      
2044 -            // (Includes having just imported default favorites)                                                  
2045 -            boolean loadedOldDb = LauncherAppState.getLauncherProvider().justLoadedOldDb();                       
2046 +                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();                         
2047 +            }                                                                                                     
2048 +                                                                                                                  
2049 +            // This code path is for our old migration code and should no longer be exercised                     
2050 +            boolean loadedOldDb = false;                                                                          
2051                                                                                                                    
2052              // Log to disk                                                                                        
2053              Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);                           
2054                                                                                                                    
2055              synchronized (sBgLock) {                                                                              
2056                  clearSBgDataStructures();                                                                         
2057 +                final HashSet<String> installingPkgs = PackageInstallerCompat                                     
2058 +                        .getInstance(mContext).updateAndGetActiveSessionCache();                                  
2059                                                                                                                    
2060                  final ArrayList<Long> itemsToRemove = new ArrayList<Long>();                                      
2061                  final ArrayList<Long> restoredRows = new ArrayList<Long>();                                       
2062 -                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;                                    
2063 +                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION;                    
2064                  if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);                                
2065                  final Cursor c = contentResolver.query(contentUri, null, null, null, null);                       
2066                                                                                                                    
2067                  // +1 for the hotseat (it can be larger than the workspace)                                       
2068                  // Load workspace in reverse order to ensure that latest items are loaded first (and              
2069                  // before any earlier duplicates)                                                                 
2070                  final HashMap<Long, ItemInfo[][]> occupied = new HashMap<Long, ItemInfo[][]>();                   
2071                                                                                                                    
2072                  try {                                                                                             
2073                      final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);                  
2074                      final int intentIndex = c.getColumnIndexOrThrow                                               
2075                              (LauncherSettings.Favorites.INTENT);                                                  
2076                      final int titleIndex = c.getColumnIndexOrThrow                                                
2077                              (LauncherSettings.Favorites.TITLE);                                                   
2078                      final int iconTypeIndex = c.getColumnIndexOrThrow(                                            
2079                              LauncherSettings.Favorites.ICON_TYPE);                                                
2080                      final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);               
2081                      final int iconPackageIndex = c.getColumnIndexOrThrow(                                         
2082                              LauncherSettings.Favorites.ICON_PACKAGE);                                             
2083                      final int iconResourceIndex = c.getColumnIndexOrThrow(                                        
2084                              LauncherSettings.Favorites.ICON_RESOURCE);                                            
2085                      final int containerIndex = c.getColumnIndexOrThrow(                                           
2086                              LauncherSettings.Favorites.CONTAINER);                                                
2087                      final int itemTypeIndex = c.getColumnIndexOrThrow(                                            
2088                              LauncherSettings.Favorites.ITEM_TYPE);                                                
2089                      final int appWidgetIdIndex = c.getColumnIndexOrThrow(                                         
2090                              LauncherSettings.Favorites.APPWIDGET_ID);                                             
2091                      final int appWidgetProviderIndex = c.getColumnIndexOrThrow(                                   
2092                              LauncherSettings.Favorites.APPWIDGET_PROVIDER);                                       
2093                      final int screenIndex = c.getColumnIndexOrThrow(                                              
2094                              LauncherSettings.Favorites.SCREEN);                                                   
2095                      final int cellXIndex = c.getColumnIndexOrThrow                                                
2096                              (LauncherSettings.Favorites.CELLX);                                                   
2097                      final int cellYIndex = c.getColumnIndexOrThrow                                                
2098                              (LauncherSettings.Favorites.CELLY);                                                   
2099                      final int spanXIndex = c.getColumnIndexOrThrow                                                
2100                              (LauncherSettings.Favorites.SPANX);                                                   
2101                      final int spanYIndex = c.getColumnIndexOrThrow(                                               
2102                              LauncherSettings.Favorites.SPANY);                                                    
2103                      final int restoredIndex = c.getColumnIndexOrThrow(                                            
2104                              LauncherSettings.Favorites.RESTORED);                                                 
2105 +                    final int profileIdIndex = c.getColumnIndexOrThrow(                                           
2106 +                            LauncherSettings.Favorites.PROFILE_ID);                                               
2107                      //final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);               
2108                      //final int displayModeIndex = c.getColumnIndexOrThrow(                                       
2109                      //        LauncherSettings.Favorites.DISPLAY_MODE);                                           
2110                                                                                                                    
2111                      ShortcutInfo info;                                                                            
2112                      String intentDescription;                                                                     
2113                      LauncherAppWidgetInfo appWidgetInfo;                                                          
2114                      int container;                                                                                
2115                      long id;                                                                                      
2116                      Intent intent;                                                                                
2117 +                    UserHandleCompat user;                                                                        
2118                                                                                                                    
2119                      while (!mStopped && c.moveToNext()) {                                                         
2120                          AtomicBoolean deleteOnInvalidPlacement = new AtomicBoolean(false);                        
2121                          try {                                                                                     
2122                              int itemType = c.getInt(itemTypeIndex);                                               
2123                              boolean restored = 0 != c.getInt(restoredIndex);                                      
2124 +                            boolean allowMissingTarget = false;                                                   
2125                                                                                                                    
2126                              switch (itemType) {                                                                   
2127                              case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:                                
2128                              case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:                                   
2129                                  id = c.getLong(idIndex);                                                          
2130                                  intentDescription = c.getString(intentIndex);                                     
2131 +                                long serialNumber = c.getInt(profileIdIndex);                                     
2132 +                                user = mUserManager.getUserForSerialNumber(serialNumber);                         
2133 +                                int promiseType = c.getInt(restoredIndex);                                        
2134 +                                if (user == null) {                                                               
2135 +                                    // User has been deleted remove the item.                                     
2136 +                                    itemsToRemove.add(id);                                                        
2137 +                                    continue;                                                                     
2138 +                                }                                                                                 
2139                                  try {                                                                             
2140                                      intent = Intent.parseUri(intentDescription, 0);                               
2141                                      ComponentName cn = intent.getComponent();                                     
2142 -                                    if (cn != null && !isValidPackageComponent(manager, cn)) {                    
2143 -                                        if (restored) {                                                           
2144 -                                            // might be installed later                                           
2145 +                                    if (cn != null && cn.getPackageName() != null) {                              
2146 +                                        boolean validPkg = launcherApps.isPackageEnabledForProfile(               
2147 +                                                cn.getPackageName(), user);                                       
2148 +                                        boolean validComponent = validPkg &&                                      
2149 +                                                launcherApps.isActivityEnabledForProfile(cn, user);               
2150 +                                                                                                                  
2151 +                                        if (validComponent) {                                                     
2152 +                                            if (restored) {                                                       
2153 +                                                // no special handling necessary for this item                    
2154 +                                                restoredRows.add(id);                                             
2155 +                                                restored = false;                                                 
2156 +                                            }                                                                     
2157 +                                        } else if (validPkg) {                                                    
2158 +                                            intent = null;                                                        
2159 +                                            if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {         
2160 +                                                // We allow auto install apps to have their intent                
2161 +                                                // updated after an install.                                      
2162 +                                                intent = manager.getLaunchIntentForPackage(                       
2163 +                                                        cn.getPackageName());                                     
2164 +                                                if (intent != null) {                                             
2165 +                                                    ContentValues values = new ContentValues();                   
2166 +                                                    values.put(LauncherSettings.Favorites.INTENT,                 
2167 +                                                            intent.toUri(0));                                     
2168 +                                                    String where = BaseColumns._ID + "= ?";                       
2169 +                                                    String[] args = {Long.toString(id)};                          
2170 +                                                    contentResolver.update(contentUri, values, where, args);      
2171 +                                                }                                                                 
2172 +                                            }                                                                     
2173 +                                                                                                                  
2174 +                                            if (intent == null) {                                                 
2175 +                                                // The app is installed but the component is no                   
2176 +                                                // longer available.                                              
2177 +                                                Launcher.addDumpLog(TAG,                                          
2178 +                                                        "Invalid component removed: " + cn, true);                
2179 +                                                itemsToRemove.add(id);                                            
2180 +                                                continue;                                                         
2181 +                                            } else {                                                              
2182 +                                                // no special handling necessary for this item                    
2183 +                                                restoredRows.add(id);                                             
2184 +                                                restored = false;                                                 
2185 +                                            }                                                                     
2186 +                                        } else if (restored) {                                                    
2187 +                                            // Package is not yet available but might be                          
2188 +                                            // installed later.                                                   
2189                                              Launcher.addDumpLog(TAG,                                              
2190                                                      "package not yet restored: " + cn, true);                     
2191 +                                                                                                                  
2192 +                                            if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {         
2193 +                                                // Restore has started once.                                      
2194 +                                            } else if (installingPkgs.contains(cn.getPackageName())) {            
2195 +                                                // App restore has started. Update the flag                       
2196 +                                                promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;                 
2197 +                                                ContentValues values = new ContentValues();                       
2198 +                                                values.put(LauncherSettings.Favorites.RESTORED,                   
2199 +                                                        promiseType);                                             
2200 +                                                String where = BaseColumns._ID + "= ?";                           
2201 +                                                String[] args = {Long.toString(id)};                              
2202 +                                                contentResolver.update(contentUri, values, where, args);          
2203 +                                                                                                                  
2204 +                                            } else if (REMOVE_UNRESTORED_ICONS) {                                 
2205 +                                                Launcher.addDumpLog(TAG,                                          
2206 +                                                        "Unrestored package removed: " + cn, true);               
2207 +                                                itemsToRemove.add(id);                                            
2208 +                                                continue;                                                         
2209 +                                            }                                                                     
2210 +                                        } else if (isSdCardReady) {                                               
2211 +                                            // Do not wait for external media load anymore.                       
2212 +                                            // Log the invalid package, and remove it                             
2213 +                                            Launcher.addDumpLog(TAG,                                              
2214 +                                                    "Invalid package removed: " + cn, true);                      
2215 +                                            itemsToRemove.add(id);                                                
2216 +                                            continue;                                                             
2217                                          } else {                                                                  
2218 -                                            if (!mAppsCanBeOnRemoveableStorage) {                                 
2219 -                                                // Log the invalid package, and remove it                         
2220 -                                                Launcher.addDumpLog(TAG,                                          
2221 -                                                        "Invalid package removed: " + cn, true);                  
2222 -                                                itemsToRemove.add(id);                                            
2223 -                                            } else {                                                              
2224 -                                                // If apps can be on external storage, then we just               
2225 -                                                // leave them for the user to remove (maybe add                   
2226 -                                                // visual treatment to it)                                        
2227 -                                                Launcher.addDumpLog(TAG,                                          
2228 -                                                        "Invalid package found: " + cn, true);                    
2229 +                                            // SdCard is not ready yet. Package might get available,              
2230 +                                            // once it is ready.                                                  
2231 +                                            Launcher.addDumpLog(TAG, "Invalid package: " + cn                     
2232 +                                                    + " (check again later)", true);                              
2233 +                                            HashSet<String> pkgs = sPendingPackages.get(user);                    
2234 +                                            if (pkgs == null) {                                                   
2235 +                                                pkgs = new HashSet<String>();                                     
2236 +                                                sPendingPackages.put(user, pkgs);                                 
2237                                              }                                                                     
2238 -                                            continue;                                                             
2239 +                                            pkgs.add(cn.getPackageName());                                        
2240 +                                            allowMissingTarget = true;                                            
2241 +                                            // Add the icon on the workspace anyway.                              
2242                                          }                                                                         
2243 -                                    } else if (restored) {                                                        
2244 -                                        // no special handling necessary for this restored item                   
2245 +                                    } else if (cn == null) {                                                      
2246 +                                        // For shortcuts with no component, keep them as they are                 
2247                                          restoredRows.add(id);                                                     
2248                                          restored = false;                                                         
2249                                      }                                                                             
2250                                  } catch (URISyntaxException e) {                                                  
2251                                      Launcher.addDumpLog(TAG,                                                      
2252                                              "Invalid uri: " + intentDescription, true);                           
2253                                      continue;                                                                     
2254                                  }                                                                                 
2255                                                                                                                    
2256                                  if (restored) {                                                                   
2257 -                                    Launcher.addDumpLog(TAG,                                                      
2258 -                                            "constructing info for partially restored package",                   
2259 -                                            true);                                                                
2260 -                                    info = getRestoredItemInfo(c, titleIndex);                                    
2261 -                                    intent = getRestoredItemIntent(c, context, intent);                           
2262 +                                    if (user.equals(UserHandleCompat.myUserHandle())) {                           
2263 +                                        Launcher.addDumpLog(TAG,                                                  
2264 +                                                "constructing info for partially restored package",               
2265 +                                                true);                                                            
2266 +                                        info = getRestoredItemInfo(c, titleIndex, intent, promiseType);           
2267 +                                        intent = getRestoredItemIntent(c, context, intent);                       
2268 +                                    } else {                                                                      
2269 +                                        // Don't restore items for other profiles.                                
2270 +                                        itemsToRemove.add(id);                                                    
2271 +                                        continue;                                                                 
2272 +                                    }                                                                             
2273                                  } else if (itemType ==                                                            
2274                                          LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {                       
2275 -                                    info = getShortcutInfo(manager, intent, context, c, iconIndex,                
2276 -                                            titleIndex, mLabelCache);                                             
2277 +                                    info = getShortcutInfo(manager, intent, user, context, c,                     
2278 +                                            iconIndex, titleIndex, mLabelCache, allowMissingTarget);              
2279                                  } else {                                                                          
2280                                      info = getShortcutInfo(c, context, iconTypeIndex,                             
2281                                              iconPackageIndex, iconResourceIndex, iconIndex,                       
2282                                              titleIndex);                                                          
2283                                                                                                                    
2284                                      // App shortcuts that used to be automatically added to Launcher              
2285                                      // didn't always have the correct intent flags set, so do that                
2286                                      // here                                                                       
2287                                      if (intent.getAction() != null &&                                             
2288                                          intent.getCategories() != null &&                                         
2289                                          intent.getAction().equals(Intent.ACTION_MAIN) &&                          
2290                                          intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {              
2291                                          intent.addFlags(                                                          
2292                                              Intent.FLAG_ACTIVITY_NEW_TASK |                                       
2293                                              Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);                           
2294                                      }                                                                             
2295                                  }                                                                                 
2296                                                                                                                    
2297                                  if (info != null) {                                                               
2298                                      info.id = id;                                                                 
2299                                      info.intent = intent;                                                         
2300                                      container = c.getInt(containerIndex);                                         
2301                                      info.container = container;                                                   
2302                                      info.screenId = c.getInt(screenIndex);                                        
2303                                      info.cellX = c.getInt(cellXIndex);                                            
2304                                      info.cellY = c.getInt(cellYIndex);                                            
2305                                      info.spanX = 1;                                                               
2306                                      info.spanY = 1;                                                               
2307 +                                    info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);                   
2308 +                                    info.isDisabled = isSafeMode                                                  
2309 +                                            && !Utilities.isSystemApp(context, intent);                           
2310                                                                                                                    
2311                                      // check & update map of what's occupied                                      
2312                                      deleteOnInvalidPlacement.set(false);                                          
2313                                      if (!checkItemPlacement(occupied, info, deleteOnInvalidPlacement)) {          
2314                                          if (deleteOnInvalidPlacement.get()) {                                     
2315                                              itemsToRemove.add(id);                                                
2316                                          }                                                                         
2317                                          break;                                                                    
2318                                      }                                                                             
2319                                                                                                                    
2320                                      switch (container) {                                                          
2321                                      case LauncherSettings.Favorites.CONTAINER_DESKTOP:                            
2322                                      case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                            
2323                                          sBgWorkspaceItems.add(info);                                              
2324                                          break;                                                                    
2325                                      default:                                                                      
2326                                          // Item is in a user folder                                               
2327                                          FolderInfo folderInfo =                                                   
2328                                                  findOrMakeFolder(sBgFolders, container);                          
2329                                          folderInfo.add(info);                                                     
2330                                          break;                                                                    
2331                                      }                                                                             
2332                                      sBgItemsIdMap.put(info.id, info);                                             
2333                                                                                                                    
2334                                      // now that we've loaded everthing re-save it with the                        
2335                                      // icon in case it disappears somehow.                                        
2336                                      queueIconToBeChecked(sBgDbIconCache, info, c, iconIndex);                     
2337                                  } else {                                                                          
2338                                      throw new RuntimeException("Unexpected null ShortcutInfo");                   
2339                                  }                                                                                 
2340                                  break;                                                                            
2341                                                                                                                    
2342                              case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:                                     
2343                                  id = c.getLong(idIndex);                                                          
2344                                  FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);                         
2345                                                                                                                    
2346                                  folderInfo.title = c.getString(titleIndex);                                       
2347                                  folderInfo.id = id;                                                               
2348                                  container = c.getInt(containerIndex);                                             
2349                                  folderInfo.container = container;                                                 
2350                                  folderInfo.screenId = c.getInt(screenIndex);                                      
2351                                  folderInfo.cellX = c.getInt(cellXIndex);                                          
2352                                  folderInfo.cellY = c.getInt(cellYIndex);                                          
2353                                  folderInfo.spanX = 1;                                                             
2354                                  folderInfo.spanY = 1;                                                             
2355                                                                                                                    
2356                                  // check & update map of what's occupied                                          
2357                                  deleteOnInvalidPlacement.set(false);                                              
2358                                  if (!checkItemPlacement(occupied, folderInfo,                                     
2359                                          deleteOnInvalidPlacement)) {                                              
2360                                      if (deleteOnInvalidPlacement.get()) {                                         
2361                                          itemsToRemove.add(id);                                                    
2362                                      }                                                                             
2363                                      break;                                                                        
2364                                  }                                                                                 
2365                                                                                                                    
2366                                  switch (container) {                                                              
2367                                      case LauncherSettings.Favorites.CONTAINER_DESKTOP:                            
2368                                      case LauncherSettings.Favorites.CONTAINER_HOTSEAT:                            
2369                                          sBgWorkspaceItems.add(folderInfo);                                        
2370                                          break;                                                                    
2371                                  }                                                                                 
2372                                                                                                                    
2373                                  if (restored) {                                                                   
2374                                      // no special handling required for restored folders                          
2375                                      restoredRows.add(id);                                                         
2376                                  }                                                                                 
2377                                                                                                                    
2378                                  sBgItemsIdMap.put(folderInfo.id, folderInfo);                                     
2379                                  sBgFolders.put(folderInfo.id, folderInfo);                                        
2380                                  break;                                                                            
2381                                                                                                                    
2382                              case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:                                  
2383                                  // Read all Launcher-specific widget details                                      
2384                                  int appWidgetId = c.getInt(appWidgetIdIndex);                                     
2385                                  String savedProvider = c.getString(appWidgetProviderIndex);                       
2386 -                                                                                                                  
2387                                  id = c.getLong(idIndex);                                                          
2388 -                                                                                                                  
2389 -                                final AppWidgetProviderInfo provider =                                            
2390 -                                        widgets.getAppWidgetInfo(appWidgetId);                                    
2391 -                                                                                                                  
2392 -                                if (!isSafeMode && (provider == null || provider.provider == null ||              
2393 -                                        provider.provider.getPackageName() == null)) {                            
2394 -                                    String log = "Deleting widget that isn't installed anymore: id="              
2395 -                                        + id + " appWidgetId=" + appWidgetId;                                     
2396 +                                final ComponentName component =                                                   
2397 +                                        ComponentName.unflattenFromString(savedProvider);                         
2398 +                                                                                                                  
2399 +                                final int restoreStatus = c.getInt(restoredIndex);                                
2400 +                                final boolean isIdValid = (restoreStatus &                                        
2401 +                                        LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;                            
2402 +                                                                                                                  
2403 +                                final boolean wasProviderReady = (restoreStatus &                                 
2404 +                                        LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;                      
2405 +                                                                                                                  
2406 +                                final AppWidgetProviderInfo provider = isIdValid                                  
2407 +                                        ? widgets.getAppWidgetInfo(appWidgetId)                                   
2408 +                                        : findAppWidgetProviderInfoWithComponent(context, component);             
2409 +                                                                                                                  
2410 +                                final boolean isProviderReady = isValidProvider(provider);                        
2411 +                                if (!isSafeMode && wasProviderReady && !isProviderReady) {                        
2412 +                                    String log = "Deleting widget that isn't installed anymore: "                 
2413 +                                            + "id=" + id + " appWidgetId=" + appWidgetId;                         
2414                                      Log.e(TAG, log);                                                              
2415                                      Launcher.addDumpLog(TAG, log, false);                                         
2416                                      itemsToRemove.add(id);                                                        
2417                                  } else {                                                                          
2418 -                                    appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,                        
2419 -                                            provider.provider);                                                   
2420 +                                    if (isProviderReady) {                                                        
2421 +                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,                    
2422 +                                                provider.provider);                                               
2423 +                                        int[] minSpan =                                                           
2424 +                                                Launcher.getMinSpanForWidget(context, provider);                  
2425 +                                        appWidgetInfo.minSpanX = minSpan[0];                                      
2426 +                                        appWidgetInfo.minSpanY = minSpan[1];                                      
2427 +                                                                                                                  
2428 +                                        int status = restoreStatus;                                               
2429 +                                        if (!wasProviderReady) {                                                  
2430 +                                            // If provider was not previously ready, update the                   
2431 +                                            // status and UI flag.                                                
2432 +                                                                                                                  
2433 +                                            // Id would be valid only if the widget restore broadcast was received🔵
2434 +                                            if (isIdValid) {                                                      
2435 +                                                status = LauncherAppWidgetInfo.RESTORE_COMPLETED;                 
2436 +                                            } else {                                                              
2437 +                                                status &= ~LauncherAppWidgetInfo                                  
2438 +                                                        .FLAG_PROVIDER_NOT_READY;                                 
2439 +                                            }                                                                     
2440 +                                        }                                                                         
2441 +                                        appWidgetInfo.restoreStatus = status;                                     
2442 +                                    } else {                                                                      
2443 +                                        Log.v(TAG, "Widget restore pending id=" + id                              
2444 +                                                + " appWidgetId=" + appWidgetId                                   
2445 +                                                + " status =" + restoreStatus);                                   
2446 +                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,                    
2447 +                                                component);                                                       
2448 +                                        appWidgetInfo.restoreStatus = restoreStatus;                              
2449 +                                                                                                                  
2450 +                                        if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {  
2451 +                                            // Restore has started once.                                          
2452 +                                        } else if (installingPkgs.contains(component.getPackageName())) {         
2453 +                                            // App restore has started. Update the flag                           
2454 +                                            appWidgetInfo.restoreStatus |=                                        
2455 +                                                    LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;                   
2456 +                                        } else if (REMOVE_UNRESTORED_ICONS) {                                     
2457 +                                            Launcher.addDumpLog(TAG,                                              
2458 +                                                    "Unrestored widget removed: " + component, true);             
2459 +                                            itemsToRemove.add(id);                                                
2460 +                                            continue;                                                             
2461 +                                        }                                                                         
2462 +                                    }                                                                             
2463 +                                                                                                                  
2464                                      appWidgetInfo.id = id;                                                        
2465                                      appWidgetInfo.screenId = c.getInt(screenIndex);                               
2466                                      appWidgetInfo.cellX = c.getInt(cellXIndex);                                   
2467                                      appWidgetInfo.cellY = c.getInt(cellYIndex);                                   
2468                                      appWidgetInfo.spanX = c.getInt(spanXIndex);                                   
2469                                      appWidgetInfo.spanY = c.getInt(spanYIndex);                                   
2470 -                                    int[] minSpan = Launcher.getMinSpanForWidget(context, provider);              
2471 -                                    appWidgetInfo.minSpanX = minSpan[0];                                          
2472 -                                    appWidgetInfo.minSpanY = minSpan[1];                                          
2473                                                                                                                    
2474                                      container = c.getInt(containerIndex);                                         
2475                                      if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&              
2476                                          container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {              
2477                                          Log.e(TAG, "Widget found where container != " +                           
2478                                              "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");               
2479                                          continue;                                                                 
2480                                      }                                                                             
2481                                                                                                                    
2482                                      appWidgetInfo.container = c.getInt(containerIndex);                           
2483                                      // check & update map of what's occupied                                      
2484                                      deleteOnInvalidPlacement.set(false);                                          
2485                                      if (!checkItemPlacement(occupied, appWidgetInfo,                              
2486                                              deleteOnInvalidPlacement)) {                                          
2487                                          if (deleteOnInvalidPlacement.get()) {                                     
2488                                              itemsToRemove.add(id);                                                
2489                                          }                                                                         
2490                                          break;                                                                    
2491                                      }                                                                             
2492 -                                    String providerName = provider.provider.flattenToString();                    
2493 -                                    if (!providerName.equals(savedProvider)) {                                    
2494 +                                                                                                                  
2495 +                                    String providerName = appWidgetInfo.providerName.flattenToString();           
2496 +                                    if (!providerName.equals(savedProvider) ||                                    
2497 +                                            (appWidgetInfo.restoreStatus != restoreStatus)) {                     
2498                                          ContentValues values = new ContentValues();                               
2499                                          values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER,                 
2500                                                  providerName);                                                    
2501 +                                        values.put(LauncherSettings.Favorites.RESTORED,                           
2502 +                                                appWidgetInfo.restoreStatus);                                     
2503                                          String where = BaseColumns._ID + "= ?";                                   
2504 -                                        String[] args = {Integer.toString(c.getInt(idIndex))};                    
2505 +                                        String[] args = {Long.toString(id)};                                      
2506                                          contentResolver.update(contentUri, values, where, args);                  
2507                                      }                                                                             
2508                                      sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);                           
2509                                      sBgAppWidgets.add(appWidgetInfo);                                             
2510                                  }                                                                                 
2511                                  break;                                                                            
2512                              }                                                                                     
2513                          } catch (Exception e) {                                                                   
2514                              Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);               
2515                          }                                                                                         
2516                      }                                                                                             
2517                  } finally {                                                                                       
2518                      if (c != null) {                                                                              
2519                          c.close();                                                                                
2520                      }                                                                                             
2521                  }                                                                                                 
2522                                                                                                                    
2523                  // Break early if we've stopped loading                                                           
2524                  if (mStopped) {                                                                                   
2525                      clearSBgDataStructures();                                                                     
2526                      return false;                                                                                 
2527                  }                                                                                                 
2528                                                                                                                    
2529                  if (itemsToRemove.size() > 0) {                                                                   
2530                      ContentProviderClient client = contentResolver.acquireContentProviderClient(                  
2531 -                            LauncherSettings.Favorites.CONTENT_URI);                                              
2532 +                            contentUri);                                                                          
2533                      // Remove dead items                                                                          
2534                      for (long id : itemsToRemove) {                                                               
2535                          if (DEBUG_LOADERS) {                                                                      
2536                              Log.d(TAG, "Removed id = " + id);                                                     
2537                          }                                                                                         
2538                          // Don't notify content observers                                                         
2539                          try {                                                                                     
2540                              client.delete(LauncherSettings.Favorites.getContentUri(id, false),                    
2541                                      null, null);                                                                  
2542                          } catch (RemoteException e) {                                                             
2543                              Log.w(TAG, "Could not remove id = " + id);                                            
2544                          }                                                                                         
2545                      }                                                                                             
2546                  }                                                                                                 
2547                                                                                                                    
2548                  if (restoredRows.size() > 0) {                                                                    
2549                      ContentProviderClient updater = contentResolver.acquireContentProviderClient(                 
2550 -                            LauncherSettings.Favorites.CONTENT_URI);                                              
2551 +                            contentUri);                                                                          
2552                      // Update restored items that no longer require special handling                              
2553                      try {                                                                                         
2554                          StringBuilder selectionBuilder = new StringBuilder();                                     
2555                          selectionBuilder.append(LauncherSettings.Favorites._ID);                                  
2556                          selectionBuilder.append(" IN (");                                                         
2557                          selectionBuilder.append(TextUtils.join(", ", restoredRows));                              
2558                          selectionBuilder.append(")");                                                             
2559                          ContentValues values = new ContentValues();                                               
2560                          values.put(LauncherSettings.Favorites.RESTORED, 0);                                       
2561 -                        updater.update(LauncherSettings.Favorites.CONTENT_URI,                                    
2562 +                        updater.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,                    
2563                                  values, selectionBuilder.toString(), null);                                       
2564                      } catch (RemoteException e) {                                                                 
2565                          Log.w(TAG, "Could not update restored rows");                                             
2566                      }                                                                                             
2567 +                }                                                                                                 
2568 +                                                                                                                  
2569 +                if (!isSdCardReady && !sPendingPackages.isEmpty()) {                                              
2570 +                    context.registerReceiver(new AppsAvailabilityCheck(),                                         
2571 +                            new IntentFilter(StartupReceiver.SYSTEM_READY),                                       
2572 +                            null, sWorker);                                                                       
2573                  }                                                                                                 
2574                                                                                                                    
2575                  if (loadedOldDb) {                                                                                
2576                      long maxScreenId = 0;                                                                         
2577                      // If we're importing we use the old screen order.                                            
2578                      for (ItemInfo item: sBgItemsIdMap.values()) {                                                 
2579                          long screenId = item.screenId;                                                            
2580                          if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                     
2581                                  !sBgWorkspaceScreens.contains(screenId)) {                                        
2582                              sBgWorkspaceScreens.add(screenId);                                                    
2583                              if (screenId > maxScreenId) {                                                         
2584                                  maxScreenId = screenId;                                                           
2585                              }                                                                                     
2586                          }                                                                                         
2587                      }                                                                                             
2588                      Collections.sort(sBgWorkspaceScreens);                                                        
2589                      // Log to disk                                                                                
2590                      Launcher.addDumpLog(TAG, "11683562 -   maxScreenId: " + maxScreenId, true);                   
2591                      Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                               
2592                              TextUtils.join(", ", sBgWorkspaceScreens), true);                                     
2593                                                                                                                    
2594                      LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);                        
2595                      updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                                     
2596                                                                                                                    
2597                      // Update the max item id after we load an old db                                             
2598                      long maxItemId = 0;                                                                           
2599                      // If we're importing we use the old screen order.                                            
2600                      for (ItemInfo item: sBgItemsIdMap.values()) {                                                 
2601                          maxItemId = Math.max(maxItemId, item.id);                                                 
2602                      }                                                                                             
2603                      LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);                            
2604                  } else {                                                                                          
2605                      TreeMap<Integer, Long> orderedScreens = loadWorkspaceScreensDb(mContext);                     
2606                      for (Integer i : orderedScreens.keySet()) {                                                   
2607                          sBgWorkspaceScreens.add(orderedScreens.get(i));                                           
2608                      }                                                                                             
2609                      // Log to disk                                                                                
2610                      Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +                               
2611                              TextUtils.join(", ", sBgWorkspaceScreens), true);                                     
2612                                                                                                                    
2613                      // Remove any empty screens                                                                   
2614                      ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);                     
2615                      for (ItemInfo item: sBgItemsIdMap.values()) {                                                 
2616                          long screenId = item.screenId;                                                            
2617                          if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                     
2618                                  unusedScreens.contains(screenId)) {                                               
2619                              unusedScreens.remove(screenId);                                                       
2620                          }                                                                                         
2621                      }                                                                                             
2622                                                                                                                    
2623                      // If there are any empty screens remove them, and update.                                    
2624                      if (unusedScreens.size() != 0) {                                                              
2625                          // Log to disk                                                                            
2626                          Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " +                 
2627                                  TextUtils.join(", ", unusedScreens), true);                                       
2628                                                                                                                    
2629                          sBgWorkspaceScreens.removeAll(unusedScreens);                                             
2630                          updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);                                 
2631                      }                                                                                             
2632                  }                                                                                                 
2633                                                                                                                    
2634                  if (DEBUG_LOADERS) {                                                                              
2635                      Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");                   
2636                      Log.d(TAG, "workspace layout: ");                                                             
2637                      int nScreens = occupied.size();                                                               
2638                      for (int y = 0; y < countY; y++) {                                                            
2639                          String line = "";                                                                         
2640                                                                                                                    
2641                          Iterator<Long> iter = occupied.keySet().iterator();                                       
2642                          while (iter.hasNext()) {                                                                  
2643                              long screenId = iter.next();                                                          
2644                              if (screenId > 0) {                                                                   
2645                                  line += " | ";                                                                    
2646                              }                                                                                     
2647                              for (int x = 0; x < countX; x++) {                                                    
2648 -                                line += ((occupied.get(screenId)[x][y] != null) ? "#" : ".");                     
2649 +                                ItemInfo[][] screen = occupied.get(screenId);                                     
2650 +                                if (x < screen.length && y < screen[x].length) {                                  
2651 +                                    line += (screen[x][y] != null) ? "#" : ".";                                   
2652 +                                } else {                                                                          
2653 +                                    line += "!";                                                                  
2654 +                                }                                                                                 
2655                              }                                                                                     
2656                          }                                                                                         
2657                          Log.d(TAG, "[ " + line + " ]");                                                           
2658                      }                                                                                             
2659                  }                                                                                                 
2660              }                                                                                                     
2661              return loadedOldDb;                                                                                   
2662          }                                                                                                         
2663                                                                                                                    
2664          /** Filters the set of items who are directly or indirectly (via another container) on the                
2665           * specified screen. */                                                                                   
2666          private void filterCurrentWorkspaceItems(long currentScreenId,                                            
2667                  ArrayList<ItemInfo> allWorkspaceItems,                                                            
2668                  ArrayList<ItemInfo> currentScreenItems,                                                           
2669                  ArrayList<ItemInfo> otherScreenItems) {                                                           
2670              // Purge any null ItemInfos                                                                           
2671              Iterator<ItemInfo> iter = allWorkspaceItems.iterator();                                               
2672              while (iter.hasNext()) {                                                                              
2673                  ItemInfo i = iter.next();                                                                         
2674                  if (i == null) {                                                                                  
2675                      iter.remove();                                                                                
2676                  }                                                                                                 
2677              }                                                                                                     
2678                                                                                                                    
2679              // Order the set of items by their containers first, this allows use to walk through the              
2680              // list sequentially, build up a list of containers that are in the specified screen,                 
2681              // as well as all items in those containers.                                                          
2682              Set<Long> itemsOnScreen = new HashSet<Long>();                                                        
2683              Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {                                      
2684                  @Override                                                                                         
2685                  public int compare(ItemInfo lhs, ItemInfo rhs) {                                                  
2686                      return (int) (lhs.container - rhs.container);                                                 
2687                  }                                                                                                 
2688              });                                                                                                   
2689              for (ItemInfo info : allWorkspaceItems) {                                                             
2690                  if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {                             
2691                      if (info.screenId == currentScreenId) {                                                       
2692                          currentScreenItems.add(info);                                                             
2693                          itemsOnScreen.add(info.id);                                                               
2694                      } else {                                                                                      
2695                          otherScreenItems.add(info);                                                               
2696                      }                                                                                             
2697                  } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {                      
2698                      currentScreenItems.add(info);                                                                 
2699                      itemsOnScreen.add(info.id);                                                                   
2700                  } else {                                                                                          
2701                      if (itemsOnScreen.contains(info.container)) {                                                 
2702                          currentScreenItems.add(info);                                                             
2703                          itemsOnScreen.add(info.id);                                                               
2704                      } else {                                                                                      
2705                          otherScreenItems.add(info);                                                               
2706                      }                                                                                             
2707                  }                                                                                                 
2708              }                                                                                                     
2709          }                                                                                                         
2710                                                                                                                    
2711          /** Filters the set of widgets which are on the specified screen. */                                      
2712          private void filterCurrentAppWidgets(long currentScreenId,                                                
2713                  ArrayList<LauncherAppWidgetInfo> appWidgets,                                                      
2714                  ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,                                            
2715                  ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {                                            
2716                                                                                                                    
2717              for (LauncherAppWidgetInfo widget : appWidgets) {                                                     
2718                  if (widget == null) continue;                                                                     
2719                  if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                           
2720                          widget.screenId == currentScreenId) {                                                     
2721                      currentScreenWidgets.add(widget);                                                             
2722                  } else {                                                                                          
2723                      otherScreenWidgets.add(widget);                                                               
2724                  }                                                                                                 
2725              }                                                                                                     
2726          }                                                                                                         
2727                                                                                                                    
2728          /** Filters the set of folders which are on the specified screen. */                                      
2729          private void filterCurrentFolders(long currentScreenId,                                                   
2730                  HashMap<Long, ItemInfo> itemsIdMap,                                                               
2731                  HashMap<Long, FolderInfo> folders,                                                                
2732                  HashMap<Long, FolderInfo> currentScreenFolders,                                                   
2733                  HashMap<Long, FolderInfo> otherScreenFolders) {                                                   
2734                                                                                                                    
2735              for (long id : folders.keySet()) {                                                                    
2736                  ItemInfo info = itemsIdMap.get(id);                                                               
2737                  FolderInfo folder = folders.get(id);                                                              
2738                  if (info == null || folder == null) continue;                                                     
2739                  if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&                             
2740                          info.screenId == currentScreenId) {                                                       
2741                      currentScreenFolders.put(id, folder);                                                         
2742                  } else {                                                                                          
2743                      otherScreenFolders.put(id, folder);                                                           
2744                  }                                                                                                 
2745              }                                                                                                     
2746          }                                                                                                         
2747                                                                                                                    
2748          /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to                   
2749           * right) */                                                                                              
2750          private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {                            
2751              final LauncherAppState app = LauncherAppState.getInstance();                                          
2752              final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();                                   
2753              // XXX: review this                                                                                   
2754              Collections.sort(workspaceItems, new Comparator<ItemInfo>() {                                         
2755                  @Override                                                                                         
2756                  public int compare(ItemInfo lhs, ItemInfo rhs) {                                                  
2757                      int cellCountX = (int) grid.numColumns;                                                       
2758                      int cellCountY = (int) grid.numRows;                                                          
2759                      int screenOffset = cellCountX * cellCountY;                                                   
2760                      int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat               
2761                      long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +                    
2762                              lhs.cellY * cellCountX + lhs.cellX);                                                  
2763                      long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +                    
2764                              rhs.cellY * cellCountX + rhs.cellX);                                                  
2765                      return (int) (lr - rr);                                                                       
2766                  }                                                                                                 
2767              });                                                                                                   
2768          }                                                                                                         
2769                                                                                                                    
2770          private void bindWorkspaceScreens(final Callbacks oldCallbacks,                                           
2771                  final ArrayList<Long> orderedScreens) {                                                           
2772              final Runnable r = new Runnable() {                                                                   
2773                  @Override                                                                                         
2774                  public void run() {                                                                               
2775                      Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                          
2776                      if (callbacks != null) {                                                                      
2777                          callbacks.bindScreens(orderedScreens);                                                    
2778                      }                                                                                             
2779                  }                                                                                                 
2780              };                                                                                                    
2781              runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                                     
2782          }                                                                                                         
2783                                                                                                                    
2784          private void bindWorkspaceItems(final Callbacks oldCallbacks,                                             
2785                  final ArrayList<ItemInfo> workspaceItems,                                                         
2786                  final ArrayList<LauncherAppWidgetInfo> appWidgets,                                                
2787                  final HashMap<Long, FolderInfo> folders,                                                          
2788                  ArrayList<Runnable> deferredBindRunnables) {                                                      
2789                                                                                                                    
2790              final boolean postOnMainThread = (deferredBindRunnables != null);                                     
2791                                                                                                                    
2792              // Bind the workspace items                                                                           
2793              int N = workspaceItems.size();                                                                        
2794              for (int i = 0; i < N; i += ITEMS_CHUNK) {                                                            
2795                  final int start = i;                                                                              
2796                  final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);                                 
2797                  final Runnable r = new Runnable() {                                                               
2798                      @Override                                                                                     
2799                      public void run() {                                                                           
2800                          Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                      
2801                          if (callbacks != null) {                                                                  
2802                              callbacks.bindItems(workspaceItems, start, start+chunkSize,                           
2803                                      false);                                                                       
2804                          }                                                                                         
2805                      }                                                                                             
2806                  };                                                                                                
2807                  if (postOnMainThread) {                                                                           
2808 -                    deferredBindRunnables.add(r);                                                                 
2809 +                    synchronized (deferredBindRunnables) {                                                        
2810 +                        deferredBindRunnables.add(r);                                                             
2811 +                    }                                                                                             
2812                  } else {                                                                                          
2813                      runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                             
2814                  }                                                                                                 
2815              }                                                                                                     
2816                                                                                                                    
2817              // Bind the folders                                                                                   
2818              if (!folders.isEmpty()) {                                                                             
2819                  final Runnable r = new Runnable() {                                                               
2820                      public void run() {                                                                           
2821                          Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                      
2822                          if (callbacks != null) {                                                                  
2823                              callbacks.bindFolders(folders);                                                       
2824                          }                                                                                         
2825                      }                                                                                             
2826                  };                                                                                                
2827                  if (postOnMainThread) {                                                                           
2828 -                    deferredBindRunnables.add(r);                                                                 
2829 +                    synchronized (deferredBindRunnables) {                                                        
2830 +                        deferredBindRunnables.add(r);                                                             
2831 +                    }                                                                                             
2832                  } else {                                                                                          
2833                      runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                             
2834                  }                                                                                                 
2835              }                                                                                                     
2836                                                                                                                    
2837              // Bind the widgets, one at a time                                                                    
2838              N = appWidgets.size();                                                                                
2839              for (int i = 0; i < N; i++) {                                                                         
2840                  final LauncherAppWidgetInfo widget = appWidgets.get(i);                                           
2841                  final Runnable r = new Runnable() {                                                               
2842                      public void run() {                                                                           
2843                          Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                      
2844                          if (callbacks != null) {                                                                  
2845                              callbacks.bindAppWidget(widget);                                                      
2846                          }                                                                                         
2847                      }                                                                                             
2848                  };                                                                                                
2849                  if (postOnMainThread) {                                                                           
2850                      deferredBindRunnables.add(r);                                                                 
2851                  } else {                                                                                          
2852                      runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                             
2853                  }                                                                                                 
2854              }                                                                                                     
2855          }                                                                                                         
2856                                                                                                                    
2857          /**                                                                                                       
2858           * Binds all loaded data to actual views on the main thread.                                              
2859           */                                                                                                       
2860          private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {                        
2861              final long t = SystemClock.uptimeMillis();                                                            
2862              Runnable r;                                                                                           
2863                                                                                                                    
2864              // Don't use these two variables in any of the callback runnables.                                    
2865              // Otherwise we hold a reference to them.                                                             
2866              final Callbacks oldCallbacks = mCallbacks.get();                                                      
2867              if (oldCallbacks == null) {                                                                           
2868                  // This launcher has exited and nobody bothered to tell us.  Just bail.                           
2869                  Log.w(TAG, "LoaderTask running with no launcher");                                                
2870                  return;                                                                                           
2871              }                                                                                                     
2872                                                                                                                    
2873              // Save a copy of all the bg-thread collections                                                       
2874              ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();                                       
2875              ArrayList<LauncherAppWidgetInfo> appWidgets =                                                         
2876                      new ArrayList<LauncherAppWidgetInfo>();                                                       
2877              HashMap<Long, FolderInfo> folders = new HashMap<Long, FolderInfo>();                                  
2878              HashMap<Long, ItemInfo> itemsIdMap = new HashMap<Long, ItemInfo>();                                   
2879              ArrayList<Long> orderedScreenIds = new ArrayList<Long>();                                             
2880              synchronized (sBgLock) {                                                                              
2881                  workspaceItems.addAll(sBgWorkspaceItems);                                                         
2882                  appWidgets.addAll(sBgAppWidgets);                                                                 
2883                  folders.putAll(sBgFolders);                                                                       
2884                  itemsIdMap.putAll(sBgItemsIdMap);                                                                 
2885                  orderedScreenIds.addAll(sBgWorkspaceScreens);                                                     
2886              }                                                                                                     
2887                                                                                                                    
2888              final boolean isLoadingSynchronously =                                                                
2889                      synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;                                        
2890              int currScreen = isLoadingSynchronously ? synchronizeBindPage :                                       
2891                  oldCallbacks.getCurrentWorkspaceScreen();                                                         
2892              if (currScreen >= orderedScreenIds.size()) {                                                          
2893                  // There may be no workspace screens (just hotseat items and an empty page).                      
2894                  currScreen = PagedView.INVALID_RESTORE_PAGE;                                                      
2895              }                                                                                                     
2896              final int currentScreen = currScreen;                                                                 
2897              final long currentScreenId = currentScreen < 0                                                        
2898                      ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);                                    
2899                                                                                                                    
2900              // Load all the items that are on the current page first (and in the process, unbind                  
2901              // all the existing workspace items before we call startBinding() below.                              
2902              unbindWorkspaceItemsOnMainThread();                                                                   
2903                                                                                                                    
2904              // Separate the items that are on the current screen, and all the other remaining items               
2905              ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();                                
2906              ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();                                  
2907              ArrayList<LauncherAppWidgetInfo> currentAppWidgets =                                                  
2908                      new ArrayList<LauncherAppWidgetInfo>();                                                       
2909              ArrayList<LauncherAppWidgetInfo> otherAppWidgets =                                                    
2910                      new ArrayList<LauncherAppWidgetInfo>();                                                       
2911              HashMap<Long, FolderInfo> currentFolders = new HashMap<Long, FolderInfo>();                           
2912              HashMap<Long, FolderInfo> otherFolders = new HashMap<Long, FolderInfo>();                             
2913                                                                                                                    
2914              filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,                   
2915                      otherWorkspaceItems);                                                                         
2916              filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,                               
2917                      otherAppWidgets);                                                                             
2918              filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,                            
2919                      otherFolders);                                                                                
2920              sortWorkspaceItemsSpatially(currentWorkspaceItems);                                                   
2921              sortWorkspaceItemsSpatially(otherWorkspaceItems);                                                     
2922                                                                                                                    
2923              // Tell the workspace that we're about to start binding items                                         
2924              r = new Runnable() {                                                                                  
2925                  public void run() {                                                                               
2926                      Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                          
2927                      if (callbacks != null) {                                                                      
2928                          callbacks.startBinding();                                                                 
2929                      }                                                                                             
2930                  }                                                                                                 
2931              };                                                                                                    
2932              runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                                     
2933                                                                                                                    
2934              bindWorkspaceScreens(oldCallbacks, orderedScreenIds);                                                 
2935                                                                                                                    
2936              // Load items on the current page                                                                     
2937              bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,                            
2938                      currentFolders, null);                                                                        
2939              if (isLoadingSynchronously) {                                                                         
2940                  r = new Runnable() {                                                                              
2941                      public void run() {                                                                           
2942                          Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                      
2943                          if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {               
2944                              callbacks.onPageBoundSynchronously(currentScreen);                                    
2945                          }                                                                                         
2946                      }                                                                                             
2947                  };                                                                                                
2948                  runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                                 
2949              }                                                                                                     
2950                                                                                                                    
2951              // Load all the remaining pages (if we are loading synchronously, we want to defer this               
2952              // work until after the first render)                                                                 
2953 -            mDeferredBindRunnables.clear();                                                                       
2954 +            synchronized (mDeferredBindRunnables) {                                                               
2955 +                mDeferredBindRunnables.clear();                                                                   
2956 +            }                                                                                                     
2957              bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,                  
2958                      (isLoadingSynchronously ? mDeferredBindRunnables : null));                                    
2959                                                                                                                    
2960              // Tell the workspace that we're done binding items                                                   
2961              r = new Runnable() {                                                                                  
2962                  public void run() {                                                                               
2963                      Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                          
2964                      if (callbacks != null) {                                                                      
2965                          callbacks.finishBindingItems(isUpgradePath);                                              
2966                      }                                                                                             
2967                                                                                                                    
2968                      // If we're profiling, ensure this is the last thing in the queue.                            
2969                      if (DEBUG_LOADERS) {                                                                          
2970                          Log.d(TAG, "bound workspace in "                                                          
2971                              + (SystemClock.uptimeMillis()-t) + "ms");                                             
2972                      }                                                                                             
2973                                                                                                                    
2974                      mIsLoadingAndBindingWorkspace = false;                                                        
2975                  }                                                                                                 
2976              };                                                                                                    
2977              if (isLoadingSynchronously) {                                                                         
2978 -                mDeferredBindRunnables.add(r);                                                                    
2979 +                synchronized (mDeferredBindRunnables) {                                                           
2980 +                    mDeferredBindRunnables.add(r);                                                                
2981 +                }                                                                                                 
2982              } else {                                                                                              
2983                  runOnMainThread(r, MAIN_THREAD_BINDING_RUNNABLE);                                                 
2984              }                                                                                                     
2985          }                                                                                                         
2986                                                                                                                    
2987          private void loadAndBindAllApps() {                                                                       
2988              if (DEBUG_LOADERS) {                                                                                  
2989                  Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);                                
2990              }                                                                                                     
2991              if (!mAllAppsLoaded) {                                                                                
2992                  loadAllApps();                                                                                    
2993                  synchronized (LoaderTask.this) {                                                                  
2994                      if (mStopped) {                                                                               
2995                          return;                                                                                   
2996                      }                                                                                             
2997                      mAllAppsLoaded = true;                                                                        
2998                  }                                                                                                 
2999              } else {                                                                                              
3000                  onlyBindAllApps();                                                                                
3001              }                                                                                                     
3002          }                                                                                                         
3003                                                                                                                    
3004          private void onlyBindAllApps() {                                                                          
3005              final Callbacks oldCallbacks = mCallbacks.get();                                                      
3006              if (oldCallbacks == null) {                                                                           
3007                  // This launcher has exited and nobody bothered to tell us.  Just bail.                           
3008                  Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");                              
3009                  return;                                                                                           
3010              }                                                                                                     
3011                                                                                                                    
3012              // shallow copy                                                                                       
3013              @SuppressWarnings("unchecked")                                                                        
3014              final ArrayList<AppInfo> list                                                                         
3015                      = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();                                           
3016              Runnable r = new Runnable() {                                                                         
3017                  public void run() {                                                                               
3018                      final long t = SystemClock.uptimeMillis();                                                    
3019                      final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                    
3020                      if (callbacks != null) {                                                                      
3021                          callbacks.bindAllApplications(list);                                                      
3022                      }                                                                                             
3023                      if (DEBUG_LOADERS) {                                                                          
3024                          Log.d(TAG, "bound all " + list.size() + " apps from cache in "                            
3025                                  + (SystemClock.uptimeMillis()-t) + "ms");                                         
3026                      }                                                                                             
3027                  }                                                                                                 
3028              };                                                                                                    
3029              boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());                    
3030              if (isRunningOnMainThread) {                                                                          
3031                  r.run();                                                                                          
3032              } else {                                                                                              
3033                  mHandler.post(r);                                                                                 
3034              }                                                                                                     
3035          }                                                                                                         
3036                                                                                                                    
3037          private void loadAllApps() {                                                                              
3038              final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                                 
3039                                                                                                                    
3040              final Callbacks oldCallbacks = mCallbacks.get();                                                      
3041              if (oldCallbacks == null) {                                                                           
3042                  // This launcher has exited and nobody bothered to tell us.  Just bail.                           
3043                  Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");                                  
3044                  return;                                                                                           
3045              }                                                                                                     
3046                                                                                                                    
3047 -            final PackageManager packageManager = mContext.getPackageManager();                                   
3048              final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);                                       
3049              mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                     
3050                                                                                                                    
3051 +            final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();                               
3052 +                                                                                                                  
3053              // Clear the list of apps                                                                             
3054              mBgAllAppsList.clear();                                                                               
3055 -                                                                                                                  
3056 -            // Query for the set of apps                                                                          
3057 -            final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                                  
3058 -            List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);                         
3059 -            if (DEBUG_LOADERS) {                                                                                  
3060 -                Log.d(TAG, "queryIntentActivities took "                                                          
3061 -                        + (SystemClock.uptimeMillis()-qiaTime) + "ms");                                           
3062 -                Log.d(TAG, "queryIntentActivities got " + apps.size() + " apps");                                 
3063 -            }                                                                                                     
3064 -            // Fail if we don't have any apps                                                                     
3065 -            if (apps == null || apps.isEmpty()) {                                                                 
3066 -                return;                                                                                           
3067 -            }                                                                                                     
3068 -            // Sort the applications by name                                                                      
3069 -            final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                                 
3070 -            Collections.sort(apps,                                                                                
3071 -                    new LauncherModel.ShortcutNameComparator(packageManager, mLabelCache));                       
3072 -            if (DEBUG_LOADERS) {                                                                                  
3073 -                Log.d(TAG, "sort took "                                                                           
3074 -                        + (SystemClock.uptimeMillis()-sortTime) + "ms");                                          
3075 -            }                                                                                                     
3076 -                                                                                                                  
3077 -            // Create the ApplicationInfos                                                                        
3078 -            for (int i = 0; i < apps.size(); i++) {                                                               
3079 -                ResolveInfo app = apps.get(i);                                                                    
3080 -                // This builds the icon bitmaps.                                                                  
3081 -                mBgAllAppsList.add(new AppInfo(packageManager, app,                                               
3082 -                        mIconCache, mLabelCache));                                                                
3083 -            }                                                                                                     
3084 -                                                                                                                  
3085 +            for (UserHandleCompat user : profiles) {                                                              
3086 +                // Query for the set of apps                                                                      
3087 +                final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                              
3088 +                List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);                
3089 +                if (DEBUG_LOADERS) {                                                                              
3090 +                    Log.d(TAG, "getActivityList took "                                                            
3091 +                            + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);                      
3092 +                    Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);                  
3093 +                }                                                                                                 
3094 +                // Fail if we don't have any apps                                                                 
3095 +                if (apps == null || apps.isEmpty()) {                                                             
3096 +                    return;                                                                                       
3097 +                }                                                                                                 
3098 +                // Sort the applications by name                                                                  
3099 +                final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;                             
3100 +                Collections.sort(apps,                                                                            
3101 +                        new LauncherModel.ShortcutNameComparator(mLabelCache));                                   
3102 +                if (DEBUG_LOADERS) {                                                                              
3103 +                    Log.d(TAG, "sort took "                                                                       
3104 +                            + (SystemClock.uptimeMillis()-sortTime) + "ms");                                      
3105 +                }                                                                                                 
3106 +                                                                                                                  
3107 +                // Create the ApplicationInfos                                                                    
3108 +                for (int i = 0; i < apps.size(); i++) {                                                           
3109 +                    LauncherActivityInfoCompat app = apps.get(i);                                                 
3110 +                    // This builds the icon bitmaps.                                                              
3111 +                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, mLabelCache));                
3112 +                }                                                                                                 
3113 +            }                                                                                                     
3114              // Huh? Shouldn't this be inside the Runnable below?                                                  
3115              final ArrayList<AppInfo> added = mBgAllAppsList.added;                                                
3116              mBgAllAppsList.added = new ArrayList<AppInfo>();                                                      
3117                                                                                                                    
3118              // Post callback on main thread                                                                       
3119              mHandler.post(new Runnable() {                                                                        
3120                  public void run() {                                                                               
3121                      final long bindTime = SystemClock.uptimeMillis();                                             
3122                      final Callbacks callbacks = tryGetCallbacks(oldCallbacks);                                    
3123                      if (callbacks != null) {                                                                      
3124                          callbacks.bindAllApplications(added);                                                     
3125                          if (DEBUG_LOADERS) {                                                                      
3126                              Log.d(TAG, "bound " + added.size() + " apps in "                                      
3127                                  + (SystemClock.uptimeMillis() - bindTime) + "ms");                                
3128                          }                                                                                         
3129                      } else {                                                                                      
3130                          Log.i(TAG, "not binding apps: no Launcher activity");                                     
3131                      }                                                                                             
3132                  }                                                                                                 
3133              });                                                                                                   
3134                                                                                                                    
3135              if (DEBUG_LOADERS) {                                                                                  
3136                  Log.d(TAG, "Icons processed in "                                                                  
3137                          + (SystemClock.uptimeMillis() - loadTime) + "ms");                                        
3138              }                                                                                                     
3139          }                                                                                                         
3140                                                                                                                    
3141          public void dumpState() {                                                                                 
3142              synchronized (sBgLock) {                                                                              
3143                  Log.d(TAG, "mLoaderTask.mContext=" + mContext);                                                   
3144                  Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);                                           
3145                  Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);                                                   
3146                  Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);                   
3147                  Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());                                            
3148              }                                                                                                     
3149          }                                                                                                         
3150      }                                                                                                             
3151                                                                                                                    
3152      void enqueuePackageUpdated(PackageUpdatedTask task) {                                                         
3153          sWorker.post(task);                                                                                       
3154      }                                                                                                             
3155                                                                                                                    
3156 +    private class AppsAvailabilityCheck extends BroadcastReceiver {                                               
3157 +                                                                                                                  
3158 +        @Override                                                                                                 
3159 +        public void onReceive(Context context, Intent intent) {                                                   
3160 +            synchronized (sBgLock) {                                                                              
3161 +                final LauncherAppsCompat launcherApps = LauncherAppsCompat                                        
3162 +                        .getInstance(mApp.getContext());                                                          
3163 +                ArrayList<String> packagesRemoved;                                                                
3164 +                for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {              
3165 +                    UserHandleCompat user = entry.getKey();                                                       
3166 +                    packagesRemoved = new ArrayList<String>();                                                    
3167 +                    for (String pkg : entry.getValue()) {                                                         
3168 +                        if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {                                
3169 +                            Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);                          
3170 +                            packagesRemoved.add(pkg);                                                             
3171 +                        }                                                                                         
3172 +                    }                                                                                             
3173 +                    if (!packagesRemoved.isEmpty()) {                                                             
3174 +                        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,                
3175 +                                packagesRemoved.toArray(new String[packagesRemoved.size()]), user));              
3176 +                    }                                                                                             
3177 +                }                                                                                                 
3178 +                sPendingPackages.clear();                                                                         
3179 +            }                                                                                                     
3180 +        }                                                                                                         
3181 +    }                                                                                                             
3182 +                                                                                                                  
3183 +    /**                                                                                                           
3184 +     * Workaround to re-check unrestored items, in-case they were installed but the Package-ADD                   
3185 +     * runnable was missed by the launcher.                                                                       
3186 +     */                                                                                                           
3187 +    public void recheckRestoredItems(final Context context) {                                                     
3188 +        Runnable r = new Runnable() {                                                                             
3189 +                                                                                                                  
3190 +            @Override                                                                                             
3191 +            public void run() {                                                                                   
3192 +                LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                        
3193 +                HashSet<String> installedPackages = new HashSet<String>();                                        
3194 +                UserHandleCompat user = UserHandleCompat.myUserHandle();                                          
3195 +                synchronized(sBgLock) {                                                                           
3196 +                    for (ItemInfo info : sBgItemsIdMap.values()) {                                                
3197 +                        if (info instanceof ShortcutInfo) {                                                       
3198 +                            ShortcutInfo si = (ShortcutInfo) info;                                                
3199 +                            if (si.isPromise() && si.getTargetComponent() != null                                 
3200 +                                    && launcherApps.isPackageEnabledForProfile(                                   
3201 +                                            si.getTargetComponent().getPackageName(), user)) {                    
3202 +                                installedPackages.add(si.getTargetComponent().getPackageName());                  
3203 +                            }                                                                                     
3204 +                        } else if (info instanceof LauncherAppWidgetInfo) {                                       
3205 +                            LauncherAppWidgetInfo widget = (LauncherAppWidgetInfo) info;                          
3206 +                            if (widget.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)              
3207 +                                    && launcherApps.isPackageEnabledForProfile(                                   
3208 +                                            widget.providerName.getPackageName(), user)) {                        
3209 +                                installedPackages.add(widget.providerName.getPackageName());                      
3210 +                            }                                                                                     
3211 +                        }                                                                                         
3212 +                    }                                                                                             
3213 +                }                                                                                                 
3214 +                                                                                                                  
3215 +                if (!installedPackages.isEmpty()) {                                                               
3216 +                    final ArrayList<AppInfo> restoredApps = new ArrayList<AppInfo>();                             
3217 +                    for (String pkg : installedPackages) {                                                        
3218 +                        for (LauncherActivityInfoCompat info : launcherApps.getActivityList(pkg, user)) {         
3219 +                            restoredApps.add(new AppInfo(context, info, user, mIconCache, null));                 
3220 +                        }                                                                                         
3221 +                    }                                                                                             
3222 +                                                                                                                  
3223 +                    final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                     
3224 +                    if (!restoredApps.isEmpty()) {                                                                
3225 +                        mHandler.post(new Runnable() {                                                            
3226 +                            public void run() {                                                                   
3227 +                                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                      
3228 +                                if (callbacks == cb && cb != null) {                                              
3229 +                                    callbacks.bindAppsRestored(restoredApps);                                     
3230 +                                }                                                                                 
3231 +                            }                                                                                     
3232 +                        });                                                                                       
3233 +                    }                                                                                             
3234 +                                                                                                                  
3235 +                }                                                                                                 
3236 +            }                                                                                                     
3237 +        };                                                                                                        
3238 +        sWorker.post(r);                                                                                          
3239 +    }                                                                                                             
3240 +                                                                                                                  
3241      private class PackageUpdatedTask implements Runnable {                                                        
3242          int mOp;                                                                                                  
3243          String[] mPackages;                                                                                       
3244 +        UserHandleCompat mUser;                                                                                   
3245                                                                                                                    
3246          public static final int OP_NONE = 0;                                                                      
3247          public static final int OP_ADD = 1;                                                                       
3248          public static final int OP_UPDATE = 2;                                                                    
3249          public static final int OP_REMOVE = 3; // uninstlled                                                      
3250          public static final int OP_UNAVAILABLE = 4; // external media unmounted                                   
3251                                                                                                                    
3252                                                                                                                    
3253 -        public PackageUpdatedTask(int op, String[] packages) {                                                    
3254 +        public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {                             
3255              mOp = op;                                                                                             
3256              mPackages = packages;                                                                                 
3257 +            mUser = user;                                                                                         
3258          }                                                                                                         
3259                                                                                                                    
3260          public void run() {                                                                                       
3261              final Context context = mApp.getContext();                                                            
3262                                                                                                                    
3263              final String[] packages = mPackages;                                                                  
3264              final int N = packages.length;                                                                        
3265              switch (mOp) {                                                                                        
3266                  case OP_ADD:                                                                                      
3267                      for (int i=0; i<N; i++) {                                                                     
3268                          if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);                  
3269 -                        mBgAllAppsList.addPackage(context, packages[i]);                                          
3270 +                        mIconCache.remove(packages[i], mUser);                                                    
3271 +                        mBgAllAppsList.addPackage(context, packages[i], mUser);                                   
3272                      }                                                                                             
3273                      break;                                                                                        
3274                  case OP_UPDATE:                                                                                   
3275                      for (int i=0; i<N; i++) {                                                                     
3276                          if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);               
3277 -                        mBgAllAppsList.updatePackage(context, packages[i]);                                       
3278 +                        mBgAllAppsList.updatePackage(context, packages[i], mUser);                                
3279                          WidgetPreviewLoader.removePackageFromDb(                                                  
3280                                  mApp.getWidgetPreviewCacheDb(), packages[i]);                                     
3281                      }                                                                                             
3282                      break;                                                                                        
3283                  case OP_REMOVE:                                                                                   
3284                  case OP_UNAVAILABLE:                                                                              
3285                      for (int i=0; i<N; i++) {                                                                     
3286                          if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);               
3287 -                        mBgAllAppsList.removePackage(packages[i]);                                                
3288 +                        mBgAllAppsList.removePackage(packages[i], mUser);                                         
3289                          WidgetPreviewLoader.removePackageFromDb(                                                  
3290                                  mApp.getWidgetPreviewCacheDb(), packages[i]);                                     
3291                      }                                                                                             
3292                      break;                                                                                        
3293              }                                                                                                     
3294                                                                                                                    
3295              ArrayList<AppInfo> added = null;                                                                      
3296              ArrayList<AppInfo> modified = null;                                                                   
3297              final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();                                      
3298                                                                                                                    
3299              if (mBgAllAppsList.added.size() > 0) {                                                                
3300                  added = new ArrayList<AppInfo>(mBgAllAppsList.added);                                             
3301                  mBgAllAppsList.added.clear();                                                                     
3302              }                                                                                                     
3303              if (mBgAllAppsList.modified.size() > 0) {                                                             
3304                  modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);                                       
3305                  mBgAllAppsList.modified.clear();                                                                  
3306              }                                                                                                     
3307              if (mBgAllAppsList.removed.size() > 0) {                                                              
3308                  removedApps.addAll(mBgAllAppsList.removed);                                                       
3309                  mBgAllAppsList.removed.clear();                                                                   
3310              }                                                                                                     
3311                                                                                                                    
3312              final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;                             
3313              if (callbacks == null) {                                                                              
3314                  Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");                   
3315                  return;                                                                                           
3316              }                                                                                                     
3317                                                                                                                    
3318              if (added != null) {                                                                                  
3319                  // Ensure that we add all the workspace applications to the db                                    
3320 -                Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                      
3321 -                if (!LauncherAppState.isDisableAllApps()) {                                                       
3322 -                    addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added);                           
3323 +                if (LauncherAppState.isDisableAllApps()) {                                                        
3324 +                    final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);                        
3325 +                    addAndBindAddedWorkspaceApps(context, addedInfos);                                            
3326                  } else {                                                                                          
3327 -                    final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);                        
3328 -                    addAndBindAddedApps(context, addedInfos, cb, added);                                          
3329 -                }                                                                                                 
3330 -            }                                                                                                     
3331 +                    addAppsToAllApps(context, added);                                                             
3332 +                }                                                                                                 
3333 +            }                                                                                                     
3334 +                                                                                                                  
3335              if (modified != null) {                                                                               
3336                  final ArrayList<AppInfo> modifiedFinal = modified;                                                
3337                                                                                                                    
3338                  // Update the launcher db to reflect the changes                                                  
3339                  for (AppInfo a : modifiedFinal) {                                                                 
3340                      ArrayList<ItemInfo> infos =                                                                   
3341 -                            getItemInfoForComponentName(a.componentName);                                         
3342 +                            getItemInfoForComponentName(a.componentName, mUser);                                  
3343                      for (ItemInfo i : infos) {                                                                    
3344                          if (isShortcutInfoUpdateable(i)) {                                                        
3345                              ShortcutInfo info = (ShortcutInfo) i;                                                 
3346                              info.title = a.title.toString();                                                      
3347 +                            info.contentDescription = a.contentDescription;                                       
3348                              updateItemInDatabase(context, info);                                                  
3349                          }                                                                                         
3350                      }                                                                                             
3351                  }                                                                                                 
3352                                                                                                                    
3353                  mHandler.post(new Runnable() {                                                                    
3354                      public void run() {                                                                           
3355                          Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                              
3356                          if (callbacks == cb && cb != null) {                                                      
3357                              callbacks.bindAppsUpdated(modifiedFinal);                                             
3358                          }                                                                                         
3359                      }                                                                                             
3360                  });                                                                                               
3361              }                                                                                                     
3362                                                                                                                    
3363              final ArrayList<String> removedPackageNames =                                                         
3364                      new ArrayList<String>();                                                                      
3365              if (mOp == OP_REMOVE) {                                                                               
3366                  // Mark all packages in the broadcast to be removed                                               
3367                  removedPackageNames.addAll(Arrays.asList(packages));                                              
3368              } else if (mOp == OP_UPDATE) {                                                                        
3369                  // Mark disabled packages in the broadcast to be removed                                          
3370                  final PackageManager pm = context.getPackageManager();                                            
3371                  for (int i=0; i<N; i++) {                                                                         
3372 -                    if (isPackageDisabled(pm, packages[i])) {                                                     
3373 +                    if (isPackageDisabled(context, packages[i], mUser)) {                                         
3374                          removedPackageNames.add(packages[i]);                                                     
3375                      }                                                                                             
3376                  }                                                                                                 
3377              }                                                                                                     
3378              // Remove all the components associated with this package                                             
3379              for (String pn : removedPackageNames) {                                                               
3380 -                ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn);                                        
3381 -                for (ItemInfo i : infos) {                                                                        
3382 -                    deleteItemFromDatabase(context, i);                                                           
3383 -                }                                                                                                 
3384 +                deletePackageFromDatabase(context, pn, mUser);                                                    
3385              }                                                                                                     
3386              // Remove all the specific components                                                                 
3387              for (AppInfo a : removedApps) {                                                                       
3388 -                ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName);                         
3389 -                for (ItemInfo i : infos) {                                                                        
3390 -                    deleteItemFromDatabase(context, i);                                                           
3391 -                }                                                                                                 
3392 +                ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);                  
3393 +                deleteItemsFromDatabase(context, infos);                                                          
3394              }                                                                                                     
3395              if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {                                       
3396                  // Remove any queued items from the install queue                                                 
3397                  String spKey = LauncherAppState.getSharedPreferencesKey();                                        
3398                  SharedPreferences sp =                                                                            
3399                          context.getSharedPreferences(spKey, Context.MODE_PRIVATE);                                
3400                  InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames);                          
3401                  // Call the components-removed callback                                                           
3402                  mHandler.post(new Runnable() {                                                                    
3403                      public void run() {                                                                           
3404                          Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                              
3405                          if (callbacks == cb && cb != null) {                                                      
3406 -                            callbacks.bindComponentsRemoved(removedPackageNames, removedApps);                    
3407 +                            callbacks.bindComponentsRemoved(removedPackageNames, removedApps, mUser);             
3408                          }                                                                                         
3409                      }                                                                                             
3410                  });                                                                                               
3411              }                                                                                                     
3412                                                                                                                    
3413              final ArrayList<Object> widgetsAndShortcuts =                                                         
3414 -                getSortedWidgetsAndShortcuts(context);                                                            
3415 +                    getSortedWidgetsAndShortcuts(context);                                                        
3416              mHandler.post(new Runnable() {                                                                        
3417                  @Override                                                                                         
3418                  public void run() {                                                                               
3419                      Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                  
3420                      if (callbacks == cb && cb != null) {                                                          
3421                          callbacks.bindPackagesUpdated(widgetsAndShortcuts);                                       
3422                      }                                                                                             
3423                  }                                                                                                 
3424              });                                                                                                   
3425                                                                                                                    
3426              // Write all the logs to disk                                                                         
3427              mHandler.post(new Runnable() {                                                                        
3428                  public void run() {                                                                               
3429                      Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;                                  
3430                      if (callbacks == cb && cb != null) {                                                          
3431                          callbacks.dumpLogsToLocalData();                                                          
3432                      }                                                                                             
3433                  }                                                                                                 
3434              });                                                                                                   
3435          }                                                                                                         
3436      }                                                                                                             
3437                                                                                                                    
3438      // Returns a list of ResolveInfos/AppWindowInfos in sorted order                                              
3439      public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {                               
3440          PackageManager packageManager = context.getPackageManager();                                              
3441          final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();                                    
3442 -        widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders());                
3443 +        widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());                
3444 +                                                                                                                  
3445          Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);                                       
3446          widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));                     
3447 -        Collections.sort(widgetsAndShortcuts,                                                                     
3448 -            new LauncherModel.WidgetAndShortcutNameComparator(packageManager));                                   
3449 +        Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));                      
3450          return widgetsAndShortcuts;                                                                               
3451      }                                                                                                             
3452                                                                                                                    
3453 -    private static boolean isPackageDisabled(PackageManager pm, String packageName) {                             
3454 -        try {                                                                                                     
3455 -            PackageInfo pi = pm.getPackageInfo(packageName, 0);                                                   
3456 -            return !pi.applicationInfo.enabled;                                                                   
3457 -        } catch (NameNotFoundException e) {                                                                       
3458 -            // Fall through                                                                                       
3459 -        }                                                                                                         
3460 -        return false;                                                                                             
3461 -    }                                                                                                             
3462 -                                                                                                                  
3463 -    public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {                          
3464 +    private static boolean isPackageDisabled(Context context, String packageName,                                 
3465 +            UserHandleCompat user) {                                                                              
3466 +        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                          
3467 +        return !launcherApps.isPackageEnabledForProfile(packageName, user);                                       
3468 +    }                                                                                                             
3469 +                                                                                                                  
3470 +    public static boolean isValidPackageActivity(Context context, ComponentName cn,                               
3471 +            UserHandleCompat user) {                                                                              
3472          if (cn == null) {                                                                                         
3473              return false;                                                                                         
3474          }                                                                                                         
3475 -        if (isPackageDisabled(pm, cn.getPackageName())) {                                                         
3476 +        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                          
3477 +        if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {                                
3478              return false;                                                                                         
3479          }                                                                                                         
3480 -                                                                                                                  
3481 -        try {                                                                                                     
3482 -            // Check the activity                                                                                 
3483 -            PackageInfo pi = pm.getPackageInfo(cn.getPackageName(), 0);                                           
3484 -            return (pm.getActivityInfo(cn, 0) != null);                                                           
3485 -        } catch (NameNotFoundException e) {                                                                       
3486 +        return launcherApps.isActivityEnabledForProfile(cn, user);                                                
3487 +    }                                                                                                             
3488 +                                                                                                                  
3489 +    public static boolean isValidPackage(Context context, String packageName,                                     
3490 +            UserHandleCompat user) {                                                                              
3491 +        if (packageName == null) {                                                                                
3492              return false;                                                                                         
3493          }                                                                                                         
3494 +        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);                          
3495 +        return launcherApps.isPackageEnabledForProfile(packageName, user);                                        
3496      }                                                                                                             
3497                                                                                                                    
3498      /**                                                                                                           
3499       * Make an ShortcutInfo object for a restored application or shortcut item that points                        
3500       * to a package that is not yet installed on the system.                                                      
3501       */                                                                                                           
3502 -    public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex) {                                      
3503 +    public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,                         
3504 +            int promiseType) {                                                                                    
3505          final ShortcutInfo info = new ShortcutInfo();                                                             
3506 -        info.usingFallbackIcon = true;                                                                            
3507 -        info.setIcon(getFallbackIcon());                                                                          
3508 -        if (cursor != null) {                                                                                     
3509 -            info.title =  cursor.getString(titleIndex);                                                           
3510 +        info.user = UserHandleCompat.myUserHandle();                                                              
3511 +        mIconCache.getTitleAndIcon(info, intent, info.user, true);                                                
3512 +                                                                                                                  
3513 +        if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {                                               
3514 +            String title = (cursor != null) ? cursor.getString(titleIndex) : null;                                
3515 +            if (!TextUtils.isEmpty(title)) {                                                                      
3516 +                info.title = title;                                                                               
3517 +            }                                                                                                     
3518 +            info.status = ShortcutInfo.FLAG_RESTORED_ICON;                                                        
3519 +        } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {                                     
3520 +            if (TextUtils.isEmpty(info.title)) {                                                                  
3521 +                info.title = (cursor != null) ? cursor.getString(titleIndex) : "";                                
3522 +            }                                                                                                     
3523 +            info.status = ShortcutInfo.FLAG_AUTOINTALL_ICON;                                                      
3524          } else {                                                                                                  
3525 -            info.title = "";                                                                                      
3526 -        }                                                                                                         
3527 +            throw new InvalidParameterException("Invalid restoreType " + promiseType);                            
3528 +        }                                                                                                         
3529 +                                                                                                                  
3530 +        info.contentDescription = mUserManager.getBadgedLabelForUser(                                             
3531 +                info.title.toString(), info.user);                                                                
3532          info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                            
3533 +        info.promisedIntent = intent;                                                                             
3534          return info;                                                                                              
3535      }                                                                                                             
3536                                                                                                                    
3537      /**                                                                                                           
3538       * Make an Intent object for a restored application or shortcut item that points                              
3539       * to the market page for the item.                                                                           
3540       */                                                                                                           
3541      private Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {                              
3542          ComponentName componentName = intent.getComponent();                                                      
3543 -        Intent marketIntent = new Intent(Intent.ACTION_VIEW);                                                     
3544 -        Uri marketUri = new Uri.Builder()                                                                         
3545 +        return getMarketIntent(componentName.getPackageName());                                                   
3546 +    }                                                                                                             
3547 +                                                                                                                  
3548 +    static Intent getMarketIntent(String packageName) {                                                           
3549 +        return new Intent(Intent.ACTION_VIEW)                                                                     
3550 +            .setData(new Uri.Builder()                                                                            
3551                  .scheme("market")                                                                                 
3552                  .authority("details")                                                                             
3553 -                .appendQueryParameter("id", componentName.getPackageName())                                       
3554 -                .build();                                                                                         
3555 -        Log.d(TAG, "manufactured intent uri: " + marketUri.toString());                                           
3556 -        marketIntent.setData(marketUri);                                                                          
3557 -        return marketIntent;                                                                                      
3558 +                .appendQueryParameter("id", packageName)                                                          
3559 +                .build());                                                                                        
3560      }                                                                                                             
3561                                                                                                                    
3562      /**                                                                                                           
3563       * This is called from the code that adds shortcuts from the intent receiver.  This                           
3564       * doesn't have a Cursor, but                                                                                 
3565       */                                                                                                           
3566 -    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context) {                 
3567 -        return getShortcutInfo(manager, intent, context, null, -1, -1, null);                                     
3568 +    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                                    
3569 +            UserHandleCompat user, Context context) {                                                             
3570 +        return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);                        
3571      }                                                                                                             
3572                                                                                                                    
3573      /**                                                                                                           
3574       * Make an ShortcutInfo object for a shortcut that is an application.                                         
3575       *                                                                                                            
3576       * If c is not null, then it will be used to fill in missing data like the title and icon.                    
3577       */                                                                                                           
3578 -    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent, Context context,                   
3579 -            Cursor c, int iconIndex, int titleIndex, HashMap<Object, CharSequence> labelCache) {                  
3580 +    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,                                    
3581 +            UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,                      
3582 +            HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {                               
3583 +        if (user == null) {                                                                                       
3584 +            Log.d(TAG, "Null user found in getShortcutInfo");                                                     
3585 +            return null;                                                                                          
3586 +        }                                                                                                         
3587 +                                                                                                                  
3588          ComponentName componentName = intent.getComponent();                                                      
3589 +        if (componentName == null) {                                                                              
3590 +            Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);                           
3591 +            return null;                                                                                          
3592 +        }                                                                                                         
3593 +                                                                                                                  
3594 +        Intent newIntent = new Intent(intent.getAction(), null);                                                  
3595 +        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                          
3596 +        newIntent.setComponent(componentName);                                                                    
3597 +        LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);                          
3598 +        if ((lai == null) && !allowMissingTarget) {                                                               
3599 +            Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);                            
3600 +            return null;                                                                                          
3601 +        }                                                                                                         
3602 +                                                                                                                  
3603          final ShortcutInfo info = new ShortcutInfo();                                                             
3604 -        if (componentName != null && !isValidPackageComponent(manager, componentName)) {                          
3605 -            Log.d(TAG, "Invalid package found in getShortcutInfo: " + componentName);                             
3606 -            return null;                                                                                          
3607 -        } else {                                                                                                  
3608 -            try {                                                                                                 
3609 -                PackageInfo pi = manager.getPackageInfo(componentName.getPackageName(), 0);                       
3610 -                info.initFlagsAndFirstInstallTime(pi);                                                            
3611 -            } catch (NameNotFoundException e) {                                                                   
3612 -                Log.d(TAG, "getPackInfo failed for package " +                                                    
3613 -                        componentName.getPackageName());                                                          
3614 -            }                                                                                                     
3615 -        }                                                                                                         
3616 -                                                                                                                  
3617 -        // TODO: See if the PackageManager knows about this case.  If it doesn't                                  
3618 -        // then return null & delete this.                                                                        
3619                                                                                                                    
3620          // the resource -- This may implicitly give us back the fallback icon,                                    
3621          // but don't worry about that.  All we're doing with usingFallbackIcon is                                 
3622          // to avoid saving lots of copies of that in the database, and most apps                                  
3623          // have icons anyway.                                                                                     
3624 -                                                                                                                  
3625 -        // Attempt to use queryIntentActivities to get the ResolveInfo (with IntentFilter info) and               
3626 -        // if that fails, or is ambiguious, fallback to the standard way of getting the resolve info              
3627 -        // via resolveActivity().                                                                                 
3628 -        Bitmap icon = null;                                                                                       
3629 -        ResolveInfo resolveInfo = null;                                                                           
3630 -        ComponentName oldComponent = intent.getComponent();                                                       
3631 -        Intent newIntent = new Intent(intent.getAction(), null);                                                  
3632 -        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);                                                          
3633 -        newIntent.setPackage(oldComponent.getPackageName());                                                      
3634 -        List<ResolveInfo> infos = manager.queryIntentActivities(newIntent, 0);                                    
3635 -        for (ResolveInfo i : infos) {                                                                             
3636 -            ComponentName cn = new ComponentName(i.activityInfo.packageName,                                      
3637 -                    i.activityInfo.name);                                                                         
3638 -            if (cn.equals(oldComponent)) {                                                                        
3639 -                resolveInfo = i;                                                                                  
3640 -            }                                                                                                     
3641 -        }                                                                                                         
3642 -        if (resolveInfo == null) {                                                                                
3643 -            resolveInfo = manager.resolveActivity(intent, 0);                                                     
3644 -        }                                                                                                         
3645 -        if (resolveInfo != null) {                                                                                
3646 -            icon = mIconCache.getIcon(componentName, resolveInfo, labelCache);                                    
3647 -        }                                                                                                         
3648 +        Bitmap icon = mIconCache.getIcon(componentName, lai, labelCache);                                         
3649 +                                                                                                                  
3650          // the db                                                                                                 
3651          if (icon == null) {                                                                                       
3652              if (c != null) {                                                                                      
3653                  icon = getIconFromCursor(c, iconIndex, context);                                                  
3654              }                                                                                                     
3655          }                                                                                                         
3656          // the fallback icon                                                                                      
3657          if (icon == null) {                                                                                       
3658 -            icon = getFallbackIcon();                                                                             
3659 +            icon = mIconCache.getDefaultIcon(user);                                                               
3660              info.usingFallbackIcon = true;                                                                        
3661          }                                                                                                         
3662          info.setIcon(icon);                                                                                       
3663                                                                                                                    
3664 +        // From the cache.                                                                                        
3665 +        if (labelCache != null) {                                                                                 
3666 +            info.title = labelCache.get(componentName);                                                           
3667 +        }                                                                                                         
3668 +                                                                                                                  
3669          // from the resource                                                                                      
3670 -        if (resolveInfo != null) {                                                                                
3671 -            ComponentName key = LauncherModel.getComponentNameFromResolveInfo(resolveInfo);                       
3672 -            if (labelCache != null && labelCache.containsKey(key)) {                                              
3673 -                info.title = labelCache.get(key);                                                                 
3674 -            } else {                                                                                              
3675 -                info.title = resolveInfo.activityInfo.loadLabel(manager);                                         
3676 -                if (labelCache != null) {                                                                         
3677 -                    labelCache.put(key, info.title);                                                              
3678 -                }                                                                                                 
3679 +        if (info.title == null && lai != null) {                                                                  
3680 +            info.title = lai.getLabel();                                                                          
3681 +            if (labelCache != null) {                                                                             
3682 +                labelCache.put(componentName, info.title);                                                        
3683              }                                                                                                     
3684          }                                                                                                         
3685          // from the db                                                                                            
3686          if (info.title == null) {                                                                                 
3687              if (c != null) {                                                                                      
3688                  info.title =  c.getString(titleIndex);                                                            
3689              }                                                                                                     
3690          }                                                                                                         
3691          // fall back to the class name of the activity                                                            
3692          if (info.title == null) {                                                                                 
3693              info.title = componentName.getClassName();                                                            
3694          }                                                                                                         
3695          info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;                                         
3696 +        info.user = user;                                                                                         
3697 +        info.contentDescription = mUserManager.getBadgedLabelForUser(                                             
3698 +                info.title.toString(), info.user);                                                                
3699          return info;                                                                                              
3700      }                                                                                                             
3701                                                                                                                    
3702      static ArrayList<ItemInfo> filterItemInfos(Collection<ItemInfo> infos,                                        
3703              ItemInfoFilter f) {                                                                                   
3704          HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();                                                     
3705          for (ItemInfo i : infos) {                                                                                
3706              if (i instanceof ShortcutInfo) {                                                                      
3707                  ShortcutInfo info = (ShortcutInfo) i;                                                             
3708 -                ComponentName cn = info.intent.getComponent();                                                    
3709 +                ComponentName cn = info.getTargetComponent();                                                     
3710                  if (cn != null && f.filterItem(null, info, cn)) {                                                 
3711                      filtered.add(info);                                                                           
3712                  }                                                                                                 
3713              } else if (i instanceof FolderInfo) {                                                                 
3714                  FolderInfo info = (FolderInfo) i;                                                                 
3715                  for (ShortcutInfo s : info.contents) {                                                            
3716 -                    ComponentName cn = s.intent.getComponent();                                                   
3717 +                    ComponentName cn = s.getTargetComponent();                                                    
3718                      if (cn != null && f.filterItem(info, s, cn)) {                                                
3719                          filtered.add(s);                                                                          
3720                      }                                                                                             
3721                  }                                                                                                 
3722              } else if (i instanceof LauncherAppWidgetInfo) {                                                      
3723                  LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;                                           
3724                  ComponentName cn = info.providerName;                                                             
3725                  if (cn != null && f.filterItem(null, info, cn)) {                                                 
3726                      filtered.add(info);                                                                           
3727                  }                                                                                                 
3728              }                                                                                                     
3729          }                                                                                                         
3730          return new ArrayList<ItemInfo>(filtered);                                                                 
3731      }                                                                                                             
3732                                                                                                                    
3733 -    private ArrayList<ItemInfo> getItemInfoForPackageName(final String pn) {                                      
3734 +    private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,                            
3735 +            final UserHandleCompat user) {                                                                        
3736          ItemInfoFilter filter  = new ItemInfoFilter() {                                                           
3737              @Override                                                                                             
3738              public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                         
3739 -                return cn.getPackageName().equals(pn);                                                            
3740 -            }                                                                                                     
3741 -        };                                                                                                        
3742 -        return filterItemInfos(sBgItemsIdMap.values(), filter);                                                   
3743 -    }                                                                                                             
3744 -                                                                                                                  
3745 -    private ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname) {                          
3746 -        ItemInfoFilter filter  = new ItemInfoFilter() {                                                           
3747 -            @Override                                                                                             
3748 -            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {                         
3749 -                return cn.equals(cname);                                                                          
3750 +                if (info.user == null) {                                                                          
3751 +                    return cn.equals(cname);                                                                      
3752 +                } else {                                                                                          
3753 +                    return cn.equals(cname) && info.user.equals(user);                                            
3754 +                }                                                                                                 
3755              }                                                                                                     
3756          };                                                                                                        
3757          return filterItemInfos(sBgItemsIdMap.values(), filter);                                                   
3758      }                                                                                                             
3759                                                                                                                    
3760      public static boolean isShortcutInfoUpdateable(ItemInfo i) {                                                  
3761          if (i instanceof ShortcutInfo) {                                                                          
3762              ShortcutInfo info = (ShortcutInfo) i;                                                                 
3763              // We need to check for ACTION_MAIN otherwise getComponent() might                                    
3764              // return null for some shortcuts (for instance, for shortcuts to                                     
3765              // web pages.)                                                                                        
3766              Intent intent = info.intent;                                                                          
3767              ComponentName name = intent.getComponent();                                                           
3768              if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&                              
3769                      Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {                              
3770                  return true;                                                                                      
3771              }                                                                                                     
3772 +            // placeholder shortcuts get special treatment, let them through too.                                 
3773 +            if (info.isPromise()) {                                                                               
3774 +                return true;                                                                                      
3775 +            }                                                                                                     
3776          }                                                                                                         
3777          return false;                                                                                             
3778      }                                                                                                             
3779                                                                                                                    
3780      /**                                                                                                           
3781       * Make an ShortcutInfo object for a shortcut that isn't an application.                                      
3782       */                                                                                                           
3783      private ShortcutInfo getShortcutInfo(Cursor c, Context context,                                               
3784              int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex,                        
3785              int titleIndex) {                                                                                     
3786                                                                                                                    
3787          Bitmap icon = null;                                                                                       
3788          final ShortcutInfo info = new ShortcutInfo();                                                             
3789 +        // Non-app shortcuts are only supported for current user.                                                 
3790 +        info.user = UserHandleCompat.myUserHandle();                                                              
3791          info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;                                            
3792                                                                                                                    
3793          // TODO: If there's an explicit component and we can't install that, delete it.                           
3794                                                                                                                    
3795          info.title = c.getString(titleIndex);                                                                     
3796                                                                                                                    
3797          int iconType = c.getInt(iconTypeIndex);                                                                   
3798          switch (iconType) {                                                                                       
3799          case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:                                                       
3800              String packageName = c.getString(iconPackageIndex);                                                   
3801              String resourceName = c.getString(iconResourceIndex);                                                 
3802              PackageManager packageManager = context.getPackageManager();                                          
3803              info.customIcon = false;                                                                              
3804              // the resource                                                                                       
3805              try {                                                                                                 
3806                  Resources resources = packageManager.getResourcesForApplication(packageName);                     
3807                  if (resources != null) {                                                                          
3808                      final int id = resources.getIdentifier(resourceName, null, null);                             
3809                      icon = Utilities.createIconBitmap(                                                            
3810                              mIconCache.getFullResIcon(resources, id), context);                                   
3811                  }                                                                                                 
3812              } catch (Exception e) {                                                                               
3813                  // drop this.  we have other places to look for icons                                             
3814              }                                                                                                     
3815              // the db                                                                                             
3816              if (icon == null) {                                                                                   
3817                  icon = getIconFromCursor(c, iconIndex, context);                                                  
3818              }                                                                                                     
3819              // the fallback icon                                                                                  
3820              if (icon == null) {                                                                                   
3821 -                icon = getFallbackIcon();                                                                         
3822 +                icon = mIconCache.getDefaultIcon(info.user);                                                      
3823                  info.usingFallbackIcon = true;                                                                    
3824              }                                                                                                     
3825              break;                                                                                                
3826          case LauncherSettings.Favorites.ICON_TYPE_BITMAP:                                                         
3827              icon = getIconFromCursor(c, iconIndex, context);                                                      
3828              if (icon == null) {                                                                                   
3829 -                icon = getFallbackIcon();                                                                         
3830 +                icon = mIconCache.getDefaultIcon(info.user);                                                      
3831                  info.customIcon = false;                                                                          
3832                  info.usingFallbackIcon = true;                                                                    
3833              } else {                                                                                              
3834                  info.customIcon = true;                                                                           
3835              }                                                                                                     
3836              break;                                                                                                
3837          default:                                                                                                  
3838 -            icon = getFallbackIcon();                                                                             
3839 +            icon = mIconCache.getDefaultIcon(info.user);                                                          
3840              info.usingFallbackIcon = true;                                                                        
3841              info.customIcon = false;                                                                              
3842              break;                                                                                                
3843          }                                                                                                         
3844          info.setIcon(icon);                                                                                       
3845          return info;                                                                                              
3846      }                                                                                                             
3847                                                                                                                    
3848      Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context) {                                          
3849          @SuppressWarnings("all") // suppress dead code warning                                                    
3850          final boolean debug = false;                                                                              
3851          if (debug) {                                                                                              
3852              Log.d(TAG, "getIconFromCursor app="                                                                   
3853                      + c.getString(c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE)));                    
3854          }                                                                                                         
3855          byte[] data = c.getBlob(iconIndex);                                                                       
3856          try {                                                                                                     
3857              return Utilities.createIconBitmap(                                                                    
3858                      BitmapFactory.decodeByteArray(data, 0, data.length), context);                                
3859          } catch (Exception e) {                                                                                   
3860              return null;                                                                                          
3861          }                                                                                                         
3862      }                                                                                                             
3863                                                                                                                    
3864      ShortcutInfo addShortcut(Context context, Intent data, long container, int screen,                            
3865              int cellX, int cellY, boolean notify) {                                                               
3866          final ShortcutInfo info = infoFromShortcutIntent(context, data, null);                                    
3867          if (info == null) {                                                                                       
3868              return null;                                                                                          
3869          }                                                                                                         
3870          addItemToDatabase(context, info, container, screen, cellX, cellY, notify);                                
3871                                                                                                                    
3872          return info;                                                                                              
3873      }                                                                                                             
3874                                                                                                                    
3875      /**                                                                                                           
3876       * Attempts to find an AppWidgetProviderInfo that matches the given component.                                
3877       */                                                                                                           
3878 -    AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                                 
3879 +    static AppWidgetProviderInfo findAppWidgetProviderInfoWithComponent(Context context,                          
3880              ComponentName component) {                                                                            
3881          List<AppWidgetProviderInfo> widgets =                                                                     
3882              AppWidgetManager.getInstance(context).getInstalledProviders();                                        
3883          for (AppWidgetProviderInfo info : widgets) {                                                              
3884              if (info.provider.equals(component)) {                                                                
3885                  return info;                                                                                      
3886              }                                                                                                     
3887          }                                                                                                         
3888          return null;                                                                                              
3889 -    }                                                                                                             
3890 -                                                                                                                  
3891 -    /**                                                                                                           
3892 -     * Returns a list of all the widgets that can handle configuration with a particular mimeType.                
3893 -     */                                                                                                           
3894 -    List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {                 
3895 -        final PackageManager packageManager = context.getPackageManager();                                        
3896 -        final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =                                  
3897 -            new ArrayList<WidgetMimeTypeHandlerData>();                                                           
3898 -                                                                                                                  
3899 -        final Intent supportsIntent =                                                                             
3900 -            new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);                                  
3901 -        supportsIntent.setType(mimeType);                                                                         
3902 -                                                                                                                  
3903 -        // Create a set of widget configuration components that we can test against                               
3904 -        final List<AppWidgetProviderInfo> widgets =                                                               
3905 -            AppWidgetManager.getInstance(context).getInstalledProviders();                                        
3906 -        final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =                      
3907 -            new HashMap<ComponentName, AppWidgetProviderInfo>();                                                  
3908 -        for (AppWidgetProviderInfo info : widgets) {                                                              
3909 -            configurationComponentToWidget.put(info.configure, info);                                             
3910 -        }                                                                                                         
3911 -                                                                                                                  
3912 -        // Run through each of the intents that can handle this type of clip data, and cross                      
3913 -        // reference them with the components that are actual configuration components                            
3914 -        final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,                 
3915 -                PackageManager.MATCH_DEFAULT_ONLY);                                                               
3916 -        for (ResolveInfo info : activities) {                                                                     
3917 -            final ActivityInfo activityInfo = info.activityInfo;                                                  
3918 -            final ComponentName infoComponent = new ComponentName(activityInfo.packageName,                       
3919 -                    activityInfo.name);                                                                           
3920 -            if (configurationComponentToWidget.containsKey(infoComponent)) {                                      
3921 -                supportedConfigurationActivities.add(                                                             
3922 -                        new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,                                 
3923 -                                configurationComponentToWidget.get(infoComponent)));                              
3924 -            }                                                                                                     
3925 -        }                                                                                                         
3926 -        return supportedConfigurationActivities;                                                                  
3927      }                                                                                                             
3928                                                                                                                    
3929      ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {                      
3930          Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);                                    
3931          String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);                                            
3932          Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);                                  
3933                                                                                                                    
3934          if (intent == null) {                                                                                     
3935              // If the intent is null, we can't construct a valid ShortcutInfo, so we return null                  
3936              Log.e(TAG, "Can't construct ShorcutInfo with null intent");                                           
3937              return null;                                                                                          
3938          }                                                                                                         
3939                                                                                                                    
3940          Bitmap icon = null;                                                                                       
3941          boolean customIcon = false;                                                                               
3942          ShortcutIconResource iconResource = null;                                                                 
3943                                                                                                                    
3944          if (bitmap != null && bitmap instanceof Bitmap) {                                                         
3945              icon = Utilities.createIconBitmap(new FastBitmapDrawable((Bitmap)bitmap), context);                   
3946              customIcon = true;                                                                                    
3947          } else {                                                                                                  
3948              Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);                      
3949              if (extra != null && extra instanceof ShortcutIconResource) {                                         
3950                  try {                                                                                             
3951                      iconResource = (ShortcutIconResource) extra;                                                  
3952                      final PackageManager packageManager = context.getPackageManager();                            
3953                      Resources resources = packageManager.getResourcesForApplication(                              
3954                              iconResource.packageName);                                                            
3955                      final int id = resources.getIdentifier(iconResource.resourceName, null, null);                
3956                      icon = Utilities.createIconBitmap(                                                            
3957 -                            mIconCache.getFullResIcon(resources, id), context);                                   
3958 +                            mIconCache.getFullResIcon(resources, id),                                             
3959 +                            context);                                                                             
3960                  } catch (Exception e) {                                                                           
3961                      Log.w(TAG, "Could not load shortcut icon: " + extra);                                         
3962                  }                                                                                                 
3963              }                                                                                                     
3964          }                                                                                                         
3965                                                                                                                    
3966          final ShortcutInfo info = new ShortcutInfo();                                                             
3967                                                                                                                    
3968 +        // Only support intents for current user for now. Intents sent from other                                 
3969 +        // users wouldn't get here without intent forwarding anyway.                                              
3970 +        info.user = UserHandleCompat.myUserHandle();                                                              
3971          if (icon == null) {                                                                                       
3972              if (fallbackIcon != null) {                                                                           
3973                  icon = fallbackIcon;                                                                              
3974              } else {                                                                                              
3975 -                icon = getFallbackIcon();                                                                         
3976 +                icon = mIconCache.getDefaultIcon(info.user);                                                      
3977                  info.usingFallbackIcon = true;                                                                    
3978              }                                                                                                     
3979          }                                                                                                         
3980          info.setIcon(icon);                                                                                       
3981                                                                                                                    
3982          info.title = name;                                                                                        
3983 +        info.contentDescription = mUserManager.getBadgedLabelForUser(                                             
3984 +                info.title.toString(), info.user);                                                                
3985          info.intent = intent;                                                                                     
3986          info.customIcon = customIcon;                                                                             
3987          info.iconResource = iconResource;                                                                         
3988                                                                                                                    
3989          return info;                                                                                              
3990      }                                                                                                             
3991                                                                                                                    
3992      boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,                      
3993              int iconIndex) {                                                                                      
3994          // If apps can't be on SD, don't even bother.                                                             
3995          if (!mAppsCanBeOnRemoveableStorage) {                                                                     
3996              return false;                                                                                         
3997          }                                                                                                         
3998          // If this icon doesn't have a custom icon, check to see                                                  
3999          // what's stored in the DB, and if it doesn't match what                                                  
4000          // we're going to show, store what we are going to show back                                              
4001          // into the DB.  We do this so when we're loading, if the                                                 
4002          // package manager can't find an icon (for example because                                                
4003          // the app is on SD) then we can use that instead.                                                        
4004          if (!info.customIcon && !info.usingFallbackIcon) {                                                        
4005              cache.put(info, c.getBlob(iconIndex));                                                                
4006              return true;                                                                                          
4007          }                                                                                                         
4008          return false;                                                                                             
4009      }                                                                                                             
4010      void updateSavedIcon(Context context, ShortcutInfo info, byte[] data) {                                       
4011          boolean needSave = false;                                                                                 
4012          try {                                                                                                     
4013              if (data != null) {                                                                                   
4014                  Bitmap saved = BitmapFactory.decodeByteArray(data, 0, data.length);                               
4015                  Bitmap loaded = info.getIcon(mIconCache);                                                         
4016                  needSave = !saved.sameAs(loaded);                                                                 
4017              } else {                                                                                              
4018                  needSave = true;                                                                                  
4019              }                                                                                                     
4020          } catch (Exception e) {                                                                                   
4021              needSave = true;                                                                                      
4022          }                                                                                                         
4023          if (needSave) {                                                                                           
4024              Log.d(TAG, "going to save icon bitmap for info=" + info);                                             
4025              // This is slower than is ideal, but this only happens once                                           
4026              // or when the app is updated with a new icon.                                                        
4027              updateItemInDatabase(context, info);                                                                  
4028          }                                                                                                         
4029      }                                                                                                             
4030                                                                                                                    
4031      /**                                                                                                           
4032       * Return an existing FolderInfo object if we have encountered this ID previously,                            
4033       * or make a new one.                                                                                         
4034       */                                                                                                           
4035      private static FolderInfo findOrMakeFolder(HashMap<Long, FolderInfo> folders, long id) {                      
4036          // See if a placeholder was created for us already                                                        
4037          FolderInfo folderInfo = folders.get(id);                                                                  
4038          if (folderInfo == null) {                                                                                 
4039              // No placeholder -- create a new instance                                                            
4040              folderInfo = new FolderInfo();                                                                        
4041              folders.put(id, folderInfo);                                                                          
4042          }                                                                                                         
4043          return folderInfo;                                                                                        
4044      }                                                                                                             
4045                                                                                                                    
4046      public static final Comparator<AppInfo> getAppNameComparator() {                                              
4047          final Collator collator = Collator.getInstance();                                                         
4048          return new Comparator<AppInfo>() {                                                                        
4049              public final int compare(AppInfo a, AppInfo b) {                                                      
4050 -                int result = collator.compare(a.title.toString().trim(),                                          
4051 -                        b.title.toString().trim());                                                               
4052 -                if (result == 0) {                                                                                
4053 -                    result = a.componentName.compareTo(b.componentName);                                          
4054 -                }                                                                                                 
4055 -                return result;                                                                                    
4056 +                if (a.user.equals(b.user)) {                                                                      
4057 +                    int result = collator.compare(a.title.toString().trim(),                                      
4058 +                            b.title.toString().trim());                                                           
4059 +                    if (result == 0) {                                                                            
4060 +                        result = a.componentName.compareTo(b.componentName);                                      
4061 +                    }                                                                                             
4062 +                    return result;                                                                                
4063 +                } else {                                                                                          
4064 +                    // TODO Need to figure out rules for sorting                                                  
4065 +                    // profiles, this puts work second.                                                           
4066 +                    return a.user.toString().compareTo(b.user.toString());                                        
4067 +                }                                                                                                 
4068              }                                                                                                     
4069          };                                                                                                        
4070      }                                                                                                             
4071      public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR                                           
4072              = new Comparator<AppInfo>() {                                                                         
4073          public final int compare(AppInfo a, AppInfo b) {                                                          
4074              if (a.firstInstallTime < b.firstInstallTime) return 1;                                                
4075              if (a.firstInstallTime > b.firstInstallTime) return -1;                                               
4076              return 0;                                                                                             
4077          }                                                                                                         
4078      };                                                                                                            
4079 -    public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {                             
4080 -        final Collator collator = Collator.getInstance();                                                         
4081 -        return new Comparator<AppWidgetProviderInfo>() {                                                          
4082 -            public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {                          
4083 -                return collator.compare(a.label.toString().trim(), b.label.toString().trim());                    
4084 -            }                                                                                                     
4085 -        };                                                                                                        
4086 -    }                                                                                                             
4087      static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {                                      
4088          if (info.activityInfo != null) {                                                                          
4089              return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);                      
4090          } else {                                                                                                  
4091              return new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name);                        
4092          }                                                                                                         
4093      }                                                                                                             
4094 -    public static class ShortcutNameComparator implements Comparator<ResolveInfo> {                               
4095 +    public static class ShortcutNameComparator implements Comparator<LauncherActivityInfoCompat> {                
4096          private Collator mCollator;                                                                               
4097 -        private PackageManager mPackageManager;                                                                   
4098          private HashMap<Object, CharSequence> mLabelCache;                                                        
4099          ShortcutNameComparator(PackageManager pm) {                                                               
4100 -            mPackageManager = pm;                                                                                 
4101              mLabelCache = new HashMap<Object, CharSequence>();                                                    
4102              mCollator = Collator.getInstance();                                                                   
4103          }                                                                                                         
4104 -        ShortcutNameComparator(PackageManager pm, HashMap<Object, CharSequence> labelCache) {                     
4105 -            mPackageManager = pm;                                                                                 
4106 +        ShortcutNameComparator(HashMap<Object, CharSequence> labelCache) {                                        
4107              mLabelCache = labelCache;                                                                             
4108              mCollator = Collator.getInstance();                                                                   
4109          }                                                                                                         
4110 -        public final int compare(ResolveInfo a, ResolveInfo b) {                                                  
4111 -            CharSequence labelA, labelB;                                                                          
4112 -            ComponentName keyA = LauncherModel.getComponentNameFromResolveInfo(a);                                
4113 -            ComponentName keyB = LauncherModel.getComponentNameFromResolveInfo(b);                                
4114 +        public final int compare(LauncherActivityInfoCompat a, LauncherActivityInfoCompat b) {                    
4115 +            String labelA, labelB;                                                                                
4116 +            ComponentName keyA = a.getComponentName();                                                            
4117 +            ComponentName keyB = b.getComponentName();                                                            
4118              if (mLabelCache.containsKey(keyA)) {                                                                  
4119 -                labelA = mLabelCache.get(keyA);                                                                   
4120 +                labelA = mLabelCache.get(keyA).toString();                                                        
4121              } else {                                                                                              
4122 -                labelA = a.loadLabel(mPackageManager).toString().trim();                                          
4123 +                labelA = a.getLabel().toString().trim();                                                          
4124                                                                                                                    
4125                  mLabelCache.put(keyA, labelA);                                                                    
4126              }                                                                                                     
4127              if (mLabelCache.containsKey(keyB)) {                                                                  
4128 -                labelB = mLabelCache.get(keyB);                                                                   
4129 +                labelB = mLabelCache.get(keyB).toString();                                                        
4130              } else {                                                                                              
4131 -                labelB = b.loadLabel(mPackageManager).toString().trim();                                          
4132 +                labelB = b.getLabel().toString().trim();                                                          
4133                                                                                                                    
4134                  mLabelCache.put(keyB, labelB);                                                                    
4135              }                                                                                                     
4136              return mCollator.compare(labelA, labelB);                                                             
4137          }                                                                                                         
4138      };                                                                                                            
4139      public static class WidgetAndShortcutNameComparator implements Comparator<Object> {                           
4140 -        private Collator mCollator;                                                                               
4141 -        private PackageManager mPackageManager;                                                                   
4142 -        private HashMap<Object, String> mLabelCache;                                                              
4143 -        WidgetAndShortcutNameComparator(PackageManager pm) {                                                      
4144 -            mPackageManager = pm;                                                                                 
4145 +        private final AppWidgetManagerCompat mManager;                                                            
4146 +        private final PackageManager mPackageManager;                                                             
4147 +        private final HashMap<Object, String> mLabelCache;                                                        
4148 +        private final Collator mCollator;                                                                         
4149 +                                                                                                                  
4150 +        WidgetAndShortcutNameComparator(Context context) {                                                        
4151 +            mManager = AppWidgetManagerCompat.getInstance(context);                                               
4152 +            mPackageManager = context.getPackageManager();                                                        
4153              mLabelCache = new HashMap<Object, String>();                                                          
4154              mCollator = Collator.getInstance();                                                                   
4155          }                                                                                                         
4156          public final int compare(Object a, Object b) {                                                            
4157              String labelA, labelB;                                                                                
4158              if (mLabelCache.containsKey(a)) {                                                                     
4159                  labelA = mLabelCache.get(a);                                                                      
4160              } else {                                                                                              
4161 -                labelA = (a instanceof AppWidgetProviderInfo) ?                                                   
4162 -                    ((AppWidgetProviderInfo) a).label :                                                           
4163 -                    ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();                               
4164 +                labelA = (a instanceof AppWidgetProviderInfo)                                                     
4165 +                        ? mManager.loadLabel((AppWidgetProviderInfo) a)                                           
4166 +                        : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();                         
4167                  mLabelCache.put(a, labelA);                                                                       
4168              }                                                                                                     
4169              if (mLabelCache.containsKey(b)) {                                                                     
4170                  labelB = mLabelCache.get(b);                                                                      
4171              } else {                                                                                              
4172 -                labelB = (b instanceof AppWidgetProviderInfo) ?                                                   
4173 -                    ((AppWidgetProviderInfo) b).label :                                                           
4174 -                    ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();                               
4175 +                labelB = (b instanceof AppWidgetProviderInfo)                                                     
4176 +                        ? mManager.loadLabel((AppWidgetProviderInfo) b)                                           
4177 +                        : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();                         
4178                  mLabelCache.put(b, labelB);                                                                       
4179              }                                                                                                     
4180              return mCollator.compare(labelA, labelB);                                                             
4181          }                                                                                                         
4182      };                                                                                                            
4183 +                                                                                                                  
4184 +    static boolean isValidProvider(AppWidgetProviderInfo provider) {                                              
4185 +        return (provider != null) && (provider.provider != null)                                                  
4186 +                && (provider.provider.getPackageName() != null);                                                  
4187 +    }                                                                                                             
4188                                                                                                                    
4189      public void dumpState() {                                                                                     
4190          Log.d(TAG, "mCallbacks=" + mCallbacks);                                                                   
4191          AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);                           
4192          AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);                         
4193          AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);                     
4194          AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);                   
4195          if (mLoaderTask != null) {                                                                                
4196              mLoaderTask.dumpState();                                                                              
4197          } else {                                                                                                  
4198              Log.d(TAG, "mLoaderTask=null");                                                                       
4199          }                                                                                                         
4200      }                                                                                                             
4201  }